Mi piacerebbe gestire una pressione prolungata su un UITableViewCell
per stampare un "menu di accesso rapido". Qualcuno lo ha già fatto?Premere a lungo su UITableView
In particolare il gesto riconosce su UITableView
?
Mi piacerebbe gestire una pressione prolungata su un UITableViewCell
per stampare un "menu di accesso rapido". Qualcuno lo ha già fatto?Premere a lungo su UITableView
In particolare il gesto riconosce su UITableView
?
Prima aggiungere alla lunga stampa gesto riconoscitore 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];
Poi nel gestore 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);
}
}
bisogna stare attenti con questo in modo che non interferisca con il normale spillatura dell'utente del cellulare e anche notare t il cappello handleLongPress
potrebbe sparare più volte (ciò è dovuto al cambio di stato del gesture di riconoscimento).
Utilizzare la proprietà timestamp UITouch in touchesBegan per lanciare un timer o fermarlo quando touchesEnded stato licenziato
Grazie per la risposta, ma come posso rilevare quale riga è interessata dal tocco? – foOg
Potrei sbagliarmi, ma non viene fornito nulla per aiutarti a farlo. Dovrai ottenere gli indici delle celle visibili attuali con [tableView indexPathsForVisibleRows] e poi, usando alcuni calcoli (il tuo offset TableView dall'alto + X volte le righe) saprai che le coordinate del tuo dito sono su cui riga. –
Sono sicuro che c'è un modo più semplice per farlo, comunque se hai un'altra idea, sarò qui :) – foOg
sembra essere più efficiente di aggiungere il sistema di riconoscimento direttamente alla cella come illustrato di seguito:
Tap&Hold for TableView Cells, Then and Now
(scorrere fino alla esempio in basso)
In che modo l'assegnazione di un nuovo oggetto riconoscitore di gesti per ogni riga può essere più efficiente di un singolo riconoscimento per l'intera tabella? – user2393462435
Ricorda che ci sono solo poche celle create se dequeue funziona correttamente. – Ants
ho usato di Anna-Karenina risposta, e funziona quasi alla grande con un bug molto serio.
Se si utilizzano le sezioni, premendo a lungo il titolo della sezione si otterrà un risultato errato premendo la prima riga in quella sezione, ho aggiunto una versione fissa di seguito (incluso il filtraggio delle chiamate fittizie basato sul stato dei gesti, secondo il suggerimento di 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);
}
}
}
}
Ciao @marmor: voglio chiedere che è possibile identificare solo una parte di una vista che l'utente ha toccato? – Manthan
Ehi, puoi usare hitTest per questo (https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html#//apple_ref/occ/instm/UIView/hitTest: withEvent :). Controlla questa risposta per esempio su come usare: http://stackoverflow.com/a/2793253/819355 – marmor
Mentre la risposta accettata funziona. Registra più incendi, insieme alla registrazione mentre si trascina sullo schermo. Questa risposta non lo fa. Una risposta legittima copia e incolla. Grazie. – ChrisOSX
Ho messo insieme una piccola categoria su UITableView basata sull'eccellente risposta di Anna Karenina.
In questo modo avrete a disposizione un metodo di delega conveniente come quello che siete abituati a gestire le normali visualizzazioni di tabelle. 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];
}
}
}
Se si desidera utilizzare questo in un UITableViewController, probabilmente è necessario sottoclasse e conforme 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.
Puoi spiegarci un po 'di più? Hai reso la cella prototipo una proprietà nel tuo VC? –
Ecco le istruzioni chiarite che combinano la risposta di Dawn Song e la risposta di Marmor.
Trascinare una lunga pressione Gesture Recognizer e rilasciarla nella cella della tabella. Salterà in fondo alla lista a sinistra.
Collegare quindi il sistema di riconoscimento gesto allo stesso modo in cui si collegare un pulsante.
Aggiungere il codice Marmor nel gestore all'azione
- (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);
}
}
}
}
La risposta migliore a mio parere –
Il Riconoscitore di gesti a pressione lunga deve essere applicato alla vista tabella e non alla cella di visualizzazione tabella. Lasciarlo nella cella di visualizzazione tabella avrà solo la riga 0 in ascolto a premere a lungo. – Alex
risposta a Swift:
Aggiungi delegato UIGestureRecognizerDelegate
al vostro UITableViewController.
Entro 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 a Swift 3.0 (Continuatuin della risposta di Ricky a Swift)
Aggiungere il
UIGestureRecognizerDelegate
al ViewController
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)")
}
}
Swift 3 risposta, utilizzando la sintassi 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
}
Fantastico !!! Molte grazie! Ma un'ultima piccola domanda: perché il metodo handleLongPress è chiamato quando il tocco termina ??? – foOg
Non viene chiamato quando il tocco finisce ma può sparare più volte se l'utente tiene il dito sulla cella per più di 4 secondi (in questo esempio) prima di sollevarlo. Correzione – Anna
: scocca più volte per indicare i diversi stati del gesto (iniziato, modificato, terminato, ecc.). Quindi, nel metodo del gestore, controlla la proprietà di stato del riconoscitore di gesti per evitare di eseguire l'azione in ogni stato del gesto. Ad esempio: 'if (gestureRecognizer.state == UIGestureRecognizerStateBegan) ...'. – Anna