Me gustaría manejar una pulsación larga en un UITableViewCell
para imprimir un "menú de acceso rápido". ¿Alguien ya hizo esto?Pulsación larga en UITableView
Particularmente el gesto reconoce en UITableView
?
Me gustaría manejar una pulsación larga en un UITableViewCell
para imprimir un "menú de acceso rápido". ¿Alguien ya hizo esto?Pulsación larga en UITableView
Particularmente el gesto reconoce en UITableView
?
Primera añadir el reconocedor gesto pulsación larga a la vista de tabla:
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:@selector(handleLongPress:)];
lpgr.minimumPressDuration = 2.0; //seconds
lpgr.delegate = self;
[self.myTableView addGestureRecognizer:lpgr];
[lpgr release];
A continuación, en el controlador 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);
}
}
hay que tener cuidado con esto para que no interfiera con el golpeteo normal del usuario de la célula y también cuenta t sombrero handleLongPress
puede disparar varias veces (esto se debe a los cambios de estado del reconocedor de gestos).
Utilice la propiedad de marca de tiempo UITouch en touchesBegan para poner en marcha un temporizador o detenerlo cuando touchesEnded fue despedido
Gracias por su respuesta, pero ¿cómo puedo detectar qué fila está preocupada por el tacto? – foOg
Podría estar equivocado, pero no se proporciona nada para ayudarlo a hacer eso. Tendrás que obtener los índices de las celdas visibles actuales con [tableView indexPathsForVisibleRows] y luego, usando algunos cálculos (tu offset de tableView desde la parte superior + X veces las filas) sabrás que las coordenadas de tu dedo están sobre fila. –
Estoy seguro de que hay una forma más fácil de hacerlo, de todos modos si tienes otra idea, estaré aquí :) – foOg
parece ser más eficaz que aporta el reconocedor directamente a la célula, como se muestra aquí:
Tap&Hold for TableView Cells, Then and Now
(desplazarse al ejemplo en la parte inferior)
¿Cómo puede ser más eficiente la asignación de un nuevo objeto reconocedor de gestos para cada fila que un único reconocedor para toda la tabla? – user2393462435
Recuerde que solo hay unas pocas celdas creadas si dequeue funciona correctamente. – Ants
He usado de Anna-Karenina responde, y funciona casi genial con un error muy serio.
Si está utilizando secciones, presionar prolongadamente el título de la sección le dará un resultado incorrecto al presionar la primera fila en esa sección, he agregado una versión fija a continuación (incluido el filtrado de llamadas ficticias basadas en el estado del gesto, por sugerencia 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);
}
}
}
}
Hola, @marmor: Quiero preguntar ¿es posible identificar solo una parte de una vista que tocó el usuario? – Manthan
Oye, puedes usar hitTest para eso (https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html#//apple_ref/occ/instm/UIView/hitTest: withEvent :). Verifique esta respuesta, por ejemplo, sobre cómo usar: http://stackoverflow.com/a/2793253/819355 – marmor
Si bien la respuesta aceptada funciona. Registra múltiples incendios, junto con el registro mientras arrastra en la pantalla. Esta respuesta no. Una respuesta legítima de copiar y pegar. Gracias. – ChrisOSX
He reunido una pequeña categoría en UITableView basada en la excelente respuesta de Anna Karenina.
De esta manera, tendrá un método de delegado conveniente, como el que está acostumbrado cuando se trata de vistas de tabla regulares. Compruébelo usted mismo:
// 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];
}
}
}
Si desea utilizar esto en un UITableViewController, es probable que tenga una subclase y se ajustan al nuevo protocolo.
Funciona muy bien para mí, ¡espero que ayude a los demás!
Simplemente agregue UILongPressGestureRecognizer a la celda del prototipo dado en el guión gráfico, luego tire del gesto hacia el archivo .m de viewController para crear un método de acción. Lo hice como dije.
¿Puedes explicar un poco más? ¿Hiciste que la célula prototipo fuera una propiedad en tu VC? –
Aquí hay instrucciones aclaradas que combinan la respuesta de Dawn Song y la respuesta de Marmor.
Arrastra un largo Presiona Gesture Recognizer y suéltalo en tu Table Cell. Saltará al final de la lista a la izquierda.
A continuación, conecte el reconocedor gesto de la misma forma que lo haría conectar un botón.
Agregue el código de Marmor en el controlador de la acción
- (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 mejor respuesta en mi opinión –
Long Press Gesture Recognizer debe aplicarse a la vista de tabla no a la celda de vista de tabla. Dejarlo en la celda de vista de tabla solo tendrá la fila 0 escuchando la pulsación larga. – Alex
respuesta en Swift:
Añadir delegado UIGestureRecognizerDelegate
a su UITableViewController.
Dentro 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)
}
Y la función:
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)")
}
}
respuesta en Swift 3.0 (Continuatuin de la respuesta de Ricky en Swift)
Añadir la
UIGestureRecognizerDelegate
a su 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)
}
Y la función:
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 respuesta, utilizando la sintaxis moderna, la incorporación de otras respuestas, y la eliminación de código que no sean necesarios.
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
}
Awesome !!! ¡Muchas gracias! Pero una última pequeña pregunta: ¿Por qué el método handleLongPress es llamada cuando el toque finalizó? – foOg
No se llama cuando el toque finaliza, pero puede disparar varias veces si el usuario mantiene el dedo sobre la celda durante más de 4 segundos (en este ejemplo) antes de levantarlo. – Anna
Corrección: se dispara varias veces para indicar los diferentes estados del gesto (comenzó, cambió, terminó, etc.). Por lo tanto, en el método del controlador, compruebe la propiedad de estado del reconocedor de gestos para evitar realizar la acción en cada estado del gesto. Por ejemplo: 'if (gestureRecognizer.state == UIGestureRecognizerStateBegan) ...'. – Anna