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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:54:02  来源:igfitidea点击:

Long press on UITableView

iosiphoneuitableviewgesture-recognitionlong-press

提问by foOg

I would like to handle a long press on a UITableViewCellto 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 handleLongPressmay 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 UIGestureRecognizerDelegateto 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.

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

enter image description here

在此处输入图片说明

Then connect the gesture recognizer the same way you would connect a button. enter image description here

然后像连接按钮一样连接手势识别器。 在此处输入图片说明

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

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

(scroll to the example at the bottom)

(滚动到底部的示例)

回答by Ricky

Answer in Swift:

用 Swift 回答:

Add delegate UIGestureRecognizerDelegateto 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 被触发时停止计时器