ios 长按 UITableView
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3924446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Long press on UITableView
提问by foOg
I would like to handle a long press on a UITableViewCell
to print a "quick access menu".
Did someone already do this?
我想长按 aUITableViewCell
来打印“快速访问菜单”。有人已经这样做了吗?
Particularly the gesture recognize on UITableView
?
特别是手势识别UITableView
?
回答by
First add the long press gesture recognizer to the table view:
首先将长按手势识别器添加到表格视图中:
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:@selector(handleLongPress:)];
lpgr.minimumPressDuration = 2.0; //seconds
lpgr.delegate = self;
[self.myTableView addGestureRecognizer:lpgr];
[lpgr release];
Then in the gesture handler:
然后在手势处理程序中:
-(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);
}
}
You have to be careful with this so that it doesn't interfere with the user's normal tapping of the cell and also note that handleLongPress
may fire multiple times (this will be due to the gesture recognizer state changes).
您必须小心,以免干扰用户对单元格的正常点击,并注意这handleLongPress
可能会触发多次(这将是由于手势识别器状态发生变化)。
回答by marmor
I've used Anna-Karenina's answer, and it works almost great with a very serious bug.
我用安娜·卡列尼娜的答案,它的工作原理差不多大一个非常严重的错误。
If you're using sections, long-pressing the section title will give you a wrong result of pressing the first row on that section, I've added a fixed version below (including the filtering of dummy calls based on the gesture state, per Anna-Karenina suggestion).
如果您正在使用部分,长按部分标题会给您按该部分第一行的错误结果,我在下面添加了一个固定版本(包括根据手势状态过滤虚拟调用,每安娜-卡列尼娜建议)。
- (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);
}
}
}
}
回答by Ben
Answer in Swift 5 (Continuation of Ricky's answer in Swift)
Swift 5 中的回答(继续 Ricky 在 Swift 中的回答)
Add the
UIGestureRecognizerDelegate
to your ViewController
添加
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)
}
And the function:
和功能:
@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)")
}
}
回答by Ryan Heitner
Here are clarified instruction combining Dawn Song's answer and Marmor's answer.
以下是结合 Dawn Song 的回答和 Marmor 的回答的明确说明。
Drag a long Press Gesture Recognizer and drop it into your Table Cell. It will jump to the bottom of the list on the left.
将长按手势识别器拖放到表格单元格中。它将跳到左侧列表的底部。
Then connect the gesture recognizer the same way you would connect a button.
Add the code from Marmor in the the action handler
在动作处理程序中添加来自 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);
}
}
}
}
}
回答by J.R.
Looks to be more efficient to add the recognizer directly to the cell as shown here:
将识别器直接添加到单元格看起来更有效,如下所示:
Tap&Hold for TableView Cells, Then and Now
(scroll to the example at the bottom)
(滚动到底部的示例)
回答by Ricky
Answer in Swift:
用 Swift 回答:
Add delegate UIGestureRecognizerDelegate
to your UITableViewController.
将委托添加UIGestureRecognizerDelegate
到您的 UITableViewController。
Within 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)
}
And the function:
和功能:
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)")
}
}
回答by de.
I put together a little category on UITableView based on Anna Karenina's excellent answer.
我根据 Anna Karenina 的出色回答在 UITableView 上整理了一个小类别。
Like this you'll have a convenient delegate method like you're used to when dealing with regular table views. Check it out:
像这样,您将拥有一个方便的委托方法,就像您在处理常规表视图时所习惯的那样。一探究竟:
// 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];
}
}
}
If you want to use this in a UITableViewController, you probably need to subclass and conform to the new protocol.
如果你想在 UITableViewController 中使用它,你可能需要继承并遵守新的协议。
It works great for me, hope it helps others!
它对我很有用,希望它可以帮助其他人!
回答by phatmann
Swift 3 answer, using modern syntax, incorporating other answers, and eliminating unneeded code.
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
}
回答by DawnSong
Just add UILongPressGestureRecognizer to the given prototype cell in storyboard, then pull the gesture to the viewController's .m file to create an action method. I made it as I said.
只需将 UILongPressGestureRecognizer 添加到故事板中的给定原型单元格,然后将手势拉到 viewController 的 .m 文件以创建一个动作方法。我照我说的做了。
回答by Thomas Joulin
Use the UITouch timestamp property in touchesBegan to launch a timer or stop it when touchesEnded got fired
使用 touchesBegan 中的 UITouch 时间戳属性启动计时器或在 touchesEnded 被触发时停止计时器