长按UITableView

foO*_*oOg 181 iphone gesture-recognition uitableview ios long-press

我想长时间按UITableViewCell下来打印"快速访问菜单".有人已经这样做了吗?

特别是手势识别UITableView

小智 418

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

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

然后在手势处理程序中:

-(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);
    }
}
Run Code Online (Sandbox Code Playgroud)

你必须要小心这使得它不与小区的用户的正常割胶干扰,也请注意,handleLongPress可能会触发多次(这是由于手势识别状态的变化).

  • 更正:它会多次触发以指示手势的不同状态(开始,更改,结束等).因此,在处理程序方法中,检查手势识别器的state属性,以避免在手势的每个状态下执行操作.例如:`if(gestureRecognizer.state == UIGestureRecognizerStateBegan)...`. (110认同)
  • 还要在class.h文件中确认UIGestureRecognizerDelegate协议 (10认同)
  • 不要忘记,手势识别器现在可以直接在Interface Builder中添加到UI元素并通过IBAction方法连接,所以这个答案更容易;-)(只记得将识别器附加到`UITableView`,而不是` UITableViewCell` ...) (3认同)
  • 惊人的 !!!多谢!但最后一个小问题:为什么触摸结束时会调用handleLongPress方法??? (2认同)
  • 如何防止表格视图导航到单元格(如果您实现了“didSelectRowAtIndexPath”?) (2认同)

mar*_*mor 44

我已经使用了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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Rya*_*ner 19

这里结合了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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

}

  • Long Press Gesture Recognizer应该应用于表格视图而不是表格视图单元格.将其删除到表格视图单元格只会使第0行听到长按. (6认同)
  • 我认为最好的答案 (2认同)

小智 19

Swift 3.0中的答案(Ricky在Swift中的答案的继续)

添加UIGestureRecognizerDelegate到ViewController

 override func viewDidLoad() {
    super.viewDidLoad()

    //Long Press
    let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
    longPressGesture.minimumPressDuration = 0.5
    longPressGesture.delegate = self
    self.tableView.addGestureRecognizer(longPressGesture)
 }
Run Code Online (Sandbox Code Playgroud)

功能:

@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)")
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 12

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

点击并按住TableView单元格,然后和现在

(滚动到底部的示例)

  • 如何为每一行分配新的手势识别器对象比整个表的单个识别器更有效? (7认同)
  • 请记住,如果出列正常,则只创建了几个单元格. (6认同)

Ric*_*cky 9

在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)

}
Run Code Online (Sandbox Code Playgroud)

功能:

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

}
Run Code Online (Sandbox Code Playgroud)


de.*_*de. 6

我根据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];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果要在UITableViewController中使用它,则可能需要子类化并符合新协议.

它对我很有用,希望它能帮到别人!


pha*_*ann 5

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
}
Run Code Online (Sandbox Code Playgroud)