Respostas:
Primeiro, adicione o reconhecedor de gestos de pressão longa à exibição da tabela:
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:@selector(handleLongPress:)];
lpgr.minimumPressDuration = 2.0; //seconds
lpgr.delegate = self;
[self.myTableView addGestureRecognizer:lpgr];
[lpgr release];
Em seguida, no manipulador de gestos:
-(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);
}
}
Você deve ter cuidado com isso para que não interfira com o toque normal da célula no usuário e também observe que handleLongPress
pode disparar várias vezes (isso ocorrerá devido às alterações de estado do reconhecedor de gestos).
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) ...
.
UITableView
, e não ao UITableViewCell
...)
Eu usei a resposta de Anna-Karenina e funciona quase perfeitamente com um bug muito sério.
Se você estiver usando seções, pressionar longamente o título da seção fornecerá um resultado errado ao pressionar a primeira linha dessa seção. Adicionei uma versão fixa abaixo (incluindo a filtragem de chamadas falsas com base no estado do gesto, por Sugestão de 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);
}
}
}
}
Resposta em Swift 5 (continuação da resposta de Ricky em Swift)
Adicione
UIGestureRecognizerDelegate
ao seu ViewController
override func viewDidLoad() {
super.viewDidLoad()
//Long Press
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
longPressGesture.minimumPressDuration = 0.5
self.tableView.addGestureRecognizer(longPressGesture)
}
E a função:
@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)")
}
}
Aqui estão as instruções esclarecidas combinando a resposta de Dawn Song e a de Marmor.
Arraste um longo Press Gesture Recognizer e solte-o na sua célula da tabela. Irá pular para o final da lista à esquerda.
Em seguida, conecte o reconhecedor de gestos da mesma maneira que conectaria um botão.
Adicione o código do Marmor no manipulador de ações
- (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);
}
}
}
}
Parece ser mais eficiente adicionar o reconhecedor diretamente à célula, como mostrado aqui:
Toque e segure para células TableView, então e agora
(role até o exemplo na parte inferior)
Resposta em Swift:
Adicione delegado UIGestureRecognizerDelegate
ao seu UITableViewController.
No 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)
}
E a função:
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)")
}
}
Montei uma pequena categoria no UITableView com base na excelente resposta de Anna Karenina.
Assim, você terá um método de delegação conveniente, como está acostumado ao lidar com visualizações de tabela regulares. Confira:
// 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];
}
}
}
Se você deseja usar isso em um UITableViewController, provavelmente precisará subclassificar e estar em conformidade com o novo protocolo.
Funciona muito bem para mim, espero que ajude os outros!
Resposta Swift 3, usando sintaxe moderna, incorporando outras respostas e eliminando códigos desnecessários.
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
}
Basta adicionar UILongPressGestureRecognizer à célula de protótipo fornecida no storyboard e puxar o gesto para o arquivo .m do viewController para criar um método de ação. Eu fiz como eu disse.
Use a propriedade de carimbo de data / hora do UITouch em touchesBegan para iniciar um timer ou pará-lo quando toquesEnded foi demitido