我想处理在UITableViewCell
上的长按操作,以显示“快速访问菜单”。
已经有人做过这个了吗?
特别是在UITableView
上的手势识别?
我想处理在UITableViewCell
上的长按操作,以显示“快速访问菜单”。
已经有人做过这个了吗?
特别是在UITableView
上的手势识别?
首先将长按手势识别器添加到表视图:
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
可能会触发多次(这是由于手势识别器状态的变化所导致的)。
我使用了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);
}
}
}
}
在 Swift 5 中回答(Ricky 在 Swift 中的答案的延续)
将
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)")
}
}
将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 编写答案:
在你的 UITableViewController 中添加委托 UIGestureRecognizerDelegate
。
在 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)")
}
}
我根据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];
}
}
}
以下是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
}
只需在Storyboard中的给定原型单元格中添加UILongPressGestureRecognizer,然后将手势拉到viewController的.m文件中创建一个操作方法。 我按照我说的做了。
@objc
,你可以使用UITableViewDelegate
的高亮函数来替代使用UILongPressGestureRecognizer
。func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath)
func tableView(_ tableView: UITableView, didUnhighlightRowAt indexPath: IndexPath)
UITableView
中实现长按检测。var highlightStartTime: Date?
func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) {
highlightStartTime = Date()
}
func tableView(_ tableView: UITableView, didUnhighlightRowAt indexPath: IndexPath) {
// Check if the highlight duration exceeds desired long-press duration
guard let highlightStartTime,
Date().timeIntervalSince(highlightStartTime) >= 2.0
else {
return
}
// You can implement your long press here using the indexPath parameter
self.highlightStartTime = nil
}
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) ...
。 - user467105UITableView
,而不是UITableViewCell
……) - user577537