Tieni premuto a lungo su UITableView

Vorrei gestire una pressione prolungata su UITableViewCell per stampare un “menu di accesso rapido”. Qualcuno lo ha già fatto?

In particolare il gesto riconosce su UITableView ?

Per prima cosa aggiungi il riconoscitore di gesture a pressione lunga alla vista tabella:

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

Quindi nel gestore del gesto:

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

Devi stare attento con questo in modo che non interferisca con il normale picchiettamento della cella dell’utente e noti anche che handleLongPress può sparare più volte (ciò sarà dovuto alle modifiche allo stato del gesture di riconoscimento).

Ho usato la risposta di Anna-Karenina, e funziona quasi alla grande con un bug molto serio.

Se stai usando le sezioni, premendo a lungo la sezione il titolo ti darà un risultato sbagliato premendo la prima riga in quella sezione, ho aggiunto una versione fissa di seguito (incluso il filtraggio delle chiamate fittizie in base allo stato del gesto, per Suggerimento 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); } } } } 

Qui ci sono istruzioni chiarite che combinano la risposta di Dawn Song e la risposta di Marmor.

Trascina una lunga pressione Gesture Recognizer e rilasciala nella tua cella tabella. Salterà in fondo alla lista a sinistra.

inserisci la descrizione dell'immagine qui

Quindi connetti il ​​riconoscitore di gesti nello stesso modo in cui connetti un pulsante. inserisci la descrizione dell'immagine qui

Aggiungi il codice di Marmor nel gestore di azioni

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

}

Sembra essere più efficiente aggiungere il riconoscitore direttamente alla cella come mostrato qui:

Tocca e tieni premuto per le celle TableView, Then e Now

(scorrere fino all’esempio in basso)

Rispondi in Swift:

Aggiungi delegato UIGestureRecognizerDelegate al tuo UITableViewController.

All’interno di 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 la funzione:

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

Risposta in Swift 3.0 (Continuatuin della risposta di Ricky in Swift)

Aggiungi UIGestureRecognizerDelegate al UIGestureRecognizerDelegate

  override func viewDidLoad() { super.viewDidLoad() //Long Press let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress)) longPressGesture.minimumPressDuration = 0.5 longPressGesture.delegate = self self.tableView.addGestureRecognizer(longPressGesture) } 

E la funzione:

 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 == UIGestureRecognizerState.began) { print("Long press on row, at \(indexPath!.row)") } } 

Ho messo insieme una piccola categoria su UITableView basata sull’eccellente risposta di Anna Karenina.

In questo modo avrai un comodo metodo di delega come se fossi abituato a gestire le normali visualizzazioni di tabelle. Controlla:

 // UITableView+LongPress.h #import  @protocol UITableViewDelegateLongPress; @interface UITableView (LongPress)  @property(nonatomic,assign) id  delegate; - (void)addLongPressRecognizer; @end @protocol UITableViewDelegateLongPress  - (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)self.delegate tableView:self didRecognizeLongPressOnRowAtIndexPath:indexPath]; } } } 

Se si desidera utilizzare questo in un UITableViewController, è probabilmente necessario sottoclass e conformità al nuovo protocollo.

Funziona benissimo per me, spero che aiuti gli altri!

Basta aggiungere UILongPressGestureRecognizer alla cella prototipo specificata nello storyboard, quindi tirare il gesto sul file .m di viewController per creare un metodo di azione. L’ho fatto come ho detto.

Risposta Swift 3, usando la syntax moderna, incorporando altre risposte ed eliminando il codice non necessario.

 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 } 

Usa la proprietà di timestamp UITouch nei tocchi. Iniziare a lanciare un timer o fermarlo quando si tocca sparare.