长按 UITableView

发布于 2024-09-27 06:40:51 字数 114 浏览 11 评论 0原文

我想处理 UITableViewCell 上的长按来打印“快速访问菜单”。 有人已经这样做了吗?

特别是 UITableView 上的手势识别?

I would like to handle a long press on a UITableViewCell to print a "quick access menu".
Did someone already do this?

Particularly the gesture recognize on UITableView?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

陌伤ぢ 2024-10-04 06:40:51

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

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

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

电影里的梦 2024-10-04 06:40:51

我使用了安娜-卡列尼娜的答案,对于一个非常严重的错误来说它几乎可以很好地工作。

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

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

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);
            }
        }
    }
}
源来凯始玺欢你 2024-10-04 06:40:51

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

Answer in Swift 5 (Continuation of Ricky's answer in Swift)

Add the UIGestureRecognizerDelegate to your 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)")
    }
}
筱武穆 2024-10-04 06:40:51

以下是结合 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);
        }
    }
}

}

Here are clarified instruction combining Dawn Song's answer and Marmor's answer.

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

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

}

离去的眼神 2024-10-04 06:40:51

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

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

(滚动到底部的示例)

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)

韶华倾负 2024-10-04 06:40:51

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

}

Answer in Swift:

Add delegate UIGestureRecognizerDelegate to your UITableViewController.

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

}
堇色安年 2024-10-04 06:40:51

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

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

I put together a little category on UITableView based on Anna Karenina's excellent answer.

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.

It works great for me, hope it helps others!

晚雾 2024-10-04 06:40:51

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
}

Swift 3 answer, using modern syntax, incorporating other answers, and eliminating unneeded code.

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
}
勿忘初心 2024-10-04 06:40:51

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

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.

淡淡的优雅 2024-10-04 06:40:51

如果您正在寻找没有 @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 you're looking for a pure-swift answer without @objc, you can use UITableViewDelegate highlight functions instead of using a UILongPressGestureRecognizer:

func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath)
func tableView(_ tableView: UITableView, didUnhighlightRowAt indexPath: IndexPath)

By keeping a reference to the start-time of the highlight, you can easily implement long-press detection in your 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
}
终陌 2024-10-04 06:40:51

使用 TouchBegan 中的 UITouch 时间戳属性启动计时器或在 TouchEnded 触发时停止计时器

Use the UITouch timestamp property in touchesBegan to launch a timer or stop it when touchesEnded got fired

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文