长按UITableView

问题描述 投票:0回答:11

我想长按

UITableViewCell
来打印“快速访问菜单”。 有人已经这样做了吗?

特别是

UITableView
上的手势识别?

ios iphone uitableview gesture-recognition long-press
11个回答
435
投票

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

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
可能会多次触发(这将是由于手势识别器状态发生变化)。


47
投票

我使用了安娜-卡列尼娜的答案,它对于一个非常严重的错误几乎非常有效。

如果您正在使用部分,长按部分标题会给您一个按下该部分第一行的错误结果,我在下面添加了一个固定版本(包括根据手势状态过滤虚拟调用,根据安娜·卡列尼娜的建议)。

- (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);
            }
        }
    }
}

40
投票

Swift 5 中的答案(Swift 中 Ricky 的答案的延续)

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)")
    }
}

22
投票

这里是结合 Dawn Song 的答案和 Marmor 的答案的澄清说明。

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

然后以与连接按钮相同的方式连接手势识别器。

在操作处理程序中添加来自 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);
        }
    }
}

}


15
投票

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

点击并按住 TableView 单元格,当时和现在

(滚动到底部的示例)


15
投票

用 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)")
    }

}

7
投票

我根据 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 中使用它,你可能需要子类化并遵守新协议。

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


6
投票

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
}

3
投票

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


0
投票

如果您正在寻找没有

@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
}

-2
投票

在touchesBegan中使用UITouch时间戳属性来启动计时器或在touchesEnded被触发时停止计时器

© www.soinside.com 2019 - 2024. All rights reserved.