Pregunta

Me gustaría manejar una pulsación larga en una UITableViewCell para imprimir un "menú de acceso rápido". ¿Alguien ya lo hacen?

En particular, el gesto de reconocer en UITableView?

¿Fue útil?

Solución

En primer lugar poner 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 en cuenta que handleLongPress puede disparar varias veces (esto será debido a los cambios de estado gesto reconocedor).

Otros consejos

He usado la respuesta de Anna-Karenina, y funciona muy bien con casi un error muy grave.

Si está utilizando secciones, a largo presionando el título de la sección le dará un resultado erróneo de presionar la primera fila en esa sección, he añadido una versión fija a continuación (incluyendo el filtrado de llamadas ficticias basado en el gesto estado, 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);
            }
        }
    }
}

A continuación, la instrucción se aclaró la combinación de la respuesta de Dawn Song y la respuesta de Marmor.

Arrastre un largo Gesto de prensa el reconocedor y la caída en su celda de tabla. Se saltará a la parte inferior de la lista de la izquierda.

 introducir descripción de la imagen aquí

A continuación, conectar el gesto reconocedor de la misma forma que lo haría conectar un botón. introducir descripción de la imagen aquí

Agregue el código de Marmor en el gestor 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);
        }
    }
}

}

Respuesta en Swift 5 (Continuación de la respuesta de Ricky en Swift)

  

Agregue el UIGestureRecognizerDelegate a su ViewController

 override func viewDidLoad() {
    super.viewDidLoad()

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

Y la función:

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

parece ser más eficaz que aporta el reconocedor directamente a la célula como se muestra aquí:

mantener pulsado para TableView células, entonces y ahora

(desplazamiento para el ejemplo en la parte inferior)

Respuesta en Swift:

Añadir UIGestureRecognizerDelegate delegado 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)")
    }

}

Me armó un poco de categoría en UITableView basado en una excelente respuesta de Anna Karenina.

Al igual que este tendrá un método conveniente como delegado que está acostumbrado cuando se trata de puntos de vista regulares de la mesa. 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 necesita subclase y cumplen con el nuevo protocolo.

Funciona muy bien para mí, espero que ayuda a los demás!

3 Swift 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
}

Sólo tiene que añadir UILongPressGestureRecognizer a la célula prototipo dada en guión gráfico, a continuación, tire el gesto de archivo .m del viewController para crear un método de acción. Lo hice como dije.

Utilice la propiedad de marca de tiempo en UITouch touchesBegan para poner en marcha un temporizador o detenerlo cuando touchesEnded fue despedido

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top