长按UITableView

我想处理长时间按下UITableViewCell以打印“快速访问菜单”。 已经有人这么做了吗?

特别是UITableView上的手势识别。

107138 次浏览

使用TouchesBegin中的UITouch时间戳属性启动计时器或在触发TouchesEnded时停止计时器

首先,将长按手势识别器添加到表格视图:

UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:@selector(handleLongPress:)];
lpgr.minimumPressDuration = 2.0; //seconds
lpgr.delegate = self;
[self.myTableView addGestureRecognizer:lpgr];
[lpgr release];

然后在手势处理程序中:

-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
CGPoint p = [gestureRecognizer locationInView:self.myTableView];


NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:p];
if (indexPath == nil) {
NSLog(@"long press on table view but not on a row");
} else if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
NSLog(@"long press on table view at row %ld", indexPath.row);
} else {
NSLog(@"gestureRecognizer.state = %ld", gestureRecognizer.state);
}
}

您必须小心使用此功能,以免干扰用户对单元的正常敲击,并且还要注意,handleLongPress可能会触发多次(这将是由于手势识别器状态的更改)。

将识别器直接添加到单元格中看起来更有效,如下所示:

点击&;为TableView单元格、Then和Now保持

(滚动到底部的示例)

我使用了Anna-Karenina的答案,它对一个非常严重的错误几乎非常有效。

如果您正在使用部分,长按部分标题将给您一个错误的结果,即按下该部分的第一行,我已经在下面添加了一个修复版本(包括根据Anna-Karenina的建议,根据手势状态过滤虚拟呼叫)。

- (IBAction)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {


CGPoint p = [gestureRecognizer locationInView:self.tableView];


NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
if (indexPath == nil) {
NSLog(@"long press on table view but not on a row");
} else {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.isHighlighted) {
NSLog(@"long press on table view at section %d row %d", indexPath.section, indexPath.row);
}
}
}
}

我根据安娜·卡列尼娜(Anna Karenina)的精彩回答,在UITableView上整理了一个小类别。

像这样,您将拥有一个方便的委托方法,就像您在处理常规表视图时所习惯的那样。看看吧:

//  UITableView+LongPress.h


#import <UIKit/UIKit.h>


@protocol UITableViewDelegateLongPress;


@interface UITableView (LongPress) <UIGestureRecognizerDelegate>
@property(nonatomic,assign)   id <UITableViewDelegateLongPress>   delegate;
- (void)addLongPressRecognizer;
@end




@protocol UITableViewDelegateLongPress <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didRecognizeLongPressOnRowAtIndexPath:(NSIndexPath *)indexPath;
@end






//  UITableView+LongPress.m


#import "UITableView+LongPress.h"


@implementation UITableView (LongPress)
@dynamic delegate;


- (void)addLongPressRecognizer {
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:@selector(handleLongPress:)];
lpgr.minimumPressDuration = 1.2; //seconds
lpgr.delegate = self;
[self addGestureRecognizer:lpgr];
}




- (void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
CGPoint p = [gestureRecognizer locationInView:self];


NSIndexPath *indexPath = [self indexPathForRowAtPoint:p];
if (indexPath == nil) {
NSLog(@"long press on table view but not on a row");
}
else {
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
// I am not sure why I need to cast here. But it seems to be alright.
[(id<UITableViewDelegateLongPress>)self.delegate tableView:self didRecognizeLongPressOnRowAtIndexPath:indexPath];
}
}
}

如果你想在UITableViewController中使用它,你可能需要子类化并符合新的协议。

它对我很有用,希望它能帮助其他人!

只需将UILongPressGestureRecognizer添加到Storyboard中给定的原型单元中,然后将手势拖到ViewController的.m文件中以创建操作方法。 我照我说的做了。

以下是结合Dawn Song的答案和Marmor的答案的澄清说明。

将长按手势识别器拖放到表格单元格中。它将跳到左侧列表的底部。

enter image description here

然后按照连接按钮的方式连接手势识别器。 enter image description here

在操作处理程序中添加来自Marmor的代码

- (IBAction)handleLongPress:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {


CGPoint p = [sender locationInView:self.tableView];


NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
if (indexPath == nil) {
NSLog(@"long press on table view but not on a row");
} else {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.isHighlighted) {
NSLog(@"long press on table view at section %d row %d", indexPath.section, indexPath.row);
}
}
}

}

用SWIFT回答:

将委派UIGestureRecognizerDelegate添加到您的UITableViewController.

在UITableViewController中:

override func viewDidLoad() {
super.viewDidLoad()


let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
longPressGesture.minimumPressDuration = 1.0 // 1 second press
longPressGesture.delegate = self
self.tableView.addGestureRecognizer(longPressGesture)


}

以及功能:

func handleLongPress(longPressGesture:UILongPressGestureRecognizer) {


let p = longPressGesture.locationInView(self.tableView)
let indexPath = self.tableView.indexPathForRowAtPoint(p)


if indexPath == nil {
print("Long press on table view, not row.")
}
else if (longPressGesture.state == UIGestureRecognizerState.Began) {
print("Long press on row, at \(indexPath!.row)")
}


}

斯威夫特的答案5(瑞奇在斯威夫特的答案的延续)

UIGestureRecognizerDelegate添加到ViewController

 override func viewDidLoad() {
super.viewDidLoad()


//Long Press
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
longPressGesture.minimumPressDuration = 0.5
self.tableView.addGestureRecognizer(longPressGesture)
}

以及功能:

@objc func handleLongPress(longPressGesture: UILongPressGestureRecognizer) {
let p = longPressGesture.location(in: self.tableView)
let indexPath = self.tableView.indexPathForRow(at: p)
if indexPath == nil {
print("Long press on table view, not row.")
} else if longPressGesture.state == UIGestureRecognizer.State.began {
print("Long press on row, at \(indexPath!.row)")
}
}

SWIFT 3答案,使用现代语法,合并其他答案,并消除不需要的代码。

override func viewDidLoad() {
super.viewDidLoad()
let recognizer = UILongPressGestureRecognizer(target: self, action: #selector(tablePressed))
tableView.addGestureRecognizer(recognizer)
}


@IBAction func tablePressed(_ recognizer: UILongPressGestureRecognizer) {
let point = recognizer.location(in: tableView)


guard recognizer.state == .began,
let indexPath = tableView.indexPathForRow(at: point),
let cell = tableView.cellForRow(at: indexPath),
cell.isHighlighted
else {
return
}


// TODO
}