iphone - tap gesture recognizer xcode
PulsaciĆ³n larga en UITableView (10)
Me gustaría manejar una pulsación larga en una UITableViewCell
para imprimir un "menú de acceso rápido". ¿Alguien ya hizo esto?
¿Particularmente el gesto reconocido en UITableView
?
Aquí hay instrucciones aclaradas que combinan la respuesta de Dawn Song y la respuesta de Marmor.
Arrastre un largo Presione Gesture Recognizer y suéltelo en su Table Cell. Saltará al final de la lista a la izquierda.
Luego, conecta el reconocedor de gestos de la misma manera que conectarías un botón.
Agregue el código de Marmor en el controlador de 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);
}
}
}
}
He usado la respuesta de Anna-Karenina, 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 (que incluye el filtrado de llamadas ficticias basadas en el estado del gesto, por Sugerencia 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);
}
}
}
}
Parece ser más eficiente para agregar el reconocedor directamente a la celda como se muestra aquí:
Toque y mantenga presionada para celdas TableView, entonces y ahora
(desplácese al ejemplo en la parte inferior)
Primero agregue el reconocedor de gestos de 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];
Luego en el controlador 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);
}
}
Debe tener cuidado con esto para que no interfiera con el golpeteo normal de la celda por parte del usuario y también tenga en cuenta que handleLongPress
puede disparar varias veces (esto se debe a cambios en el estado del reconocedor de gestos).
Puse una pequeña categoría en UITableView basada en la excelente respuesta de Anna Karenina.
De esta manera, tendrás un conveniente método de delegado como el que estás acostumbrado cuando trabajas con vistas de tabla regulares. Echale un vistazo:
// 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 usar esto en un UITableViewController, probablemente necesite subclasificar y ajustarse al nuevo protocolo.
Funciona muy bien para mí, ¡espero que ayude a los demás!
Respuesta en Swift 3.0 (Continuatuin de la respuesta de Ricky en Swift)
Agregue el
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)")
}
}
Respuesta en Swift:
Agregue el delegado UIGestureRecognizerDelegate
a su UITableViewController.
Dentro de 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)")
}
}
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.
Swift 3 responde con sintaxis moderna, incorpora otras respuestas y elimina el código innecesario.
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
}
Use la propiedad de la marca de tiempo de UITouch en touchesBegan para iniciar un temporizador o detenerlo cuando toques encendidos fue despedido