ios - UIButton Long Press Event
objective-c long-press (8)
Quiero emular un botón de presión prolongado, ¿cómo puedo hacer esto? Creo que se necesita un temporizador. Veo UILongPressGestureRecognizer
pero ¿cómo puedo utilizar este tipo?
Versión rápida de la respuesta aceptada
Hice la modificación adicional de usar UIGestureRecognizerState.Began
lugar de .Ended
ya que es probablemente lo que la mayoría de los usuarios esperaría. Pruébalos y ve por ti mismo, sin embargo.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// add gesture recognizer
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_:)))
self.button.addGestureRecognizer(longPress)
}
func longPress(gesture: UILongPressGestureRecognizer) {
if gesture.state == UIGestureRecognizerState.began {
print("Long Press")
}
}
@IBAction func normalButtonTap(sender: UIButton) {
print("Button tapped")
}
}
Como alternativa a la respuesta aceptada, esto se puede hacer muy fácilmente en Xcode usando Interface Builder.
Simplemente arrastre un Reconocedor de gestos de pulsación larga desde la Biblioteca de objetos y colóquelo sobre el botón donde desea la acción de pulsación larga.
A continuación, conecte una Acción desde el Reconocedor de gestos de UILongPressGestureRecognizer
larga recién agregado a su controlador de vista, seleccionando el remitente para que sea del tipo UILongPressGestureRecognizer
. En el código de ese IBAction
usa esto, que es muy similar al código sugerido en la respuesta aceptada:
En Objective-C :
if ( sender.state == UIGestureRecognizerStateEnded ) {
// Do your stuff here
}
O en Swift :
if sender.state == .Ended {
// Do your stuff here
}
Pero tengo que admitir que después de probarlo, prefiero la sugerencia hecha por @shengbinmeng como un comentario a la respuesta aceptada, que era usar:
En Objective-C :
if ( sender.state == UIGestureRecognizerStateBegan ) {
// Do your stuff here
}
O en Swift :
if sender.state == .Began {
// Do your stuff here
}
La diferencia es que con Ended
, verá el efecto de la presión prolongada cuando levanta el dedo. Con Began
, verá el efecto de la pulsación larga tan pronto como el sistema capte la pulsación larga, incluso antes de levantar el dedo de la pantalla.
Creo que necesitas mi solución.
deberías tener este código para una sola pulsación
- (IBAction)buttonDidPress:(id)sender {
NSLog("buttonDidPress");
}
primero, agregue el gesto de presionar prolongadamente al botón
- (void)viewWillAppear:(BOOL)animated
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(buttonDidLongPress:)];
[self.button addGestureRecognizer:longPress];
}
luego llame al evento de una sola pulsación repetidamente si se reconoce el gesto de la presión prolongada.
- (void)buttonDidLongPress:(UILongPressGestureRecognizer*)gesture
{
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
{
self.timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(buttonDidPress:) userInfo:nil repeats:YES];
NSRunLoop * theRunLoop = [NSRunLoop currentRunLoop];
[theRunLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
}
break;
case UIGestureRecognizerStateEnded:
{
[self.timer invalidate];
self.timer = nil;
}
break;
default:
break;
}
}
Ninguno funcionó, por lo tanto, traté de escribir código de IBAction
en IBAction
o botón clic desde el storyboard
en Controller
en lugar de escribir en viewDidLoad
- (IBAction)btnClick:(id)sender {
tag = (int)((UIButton *)sender).tag;
// Long press here instead of in viewDidLoad
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
longPress.cancelsTouchesInView = NO;
[sender addGestureRecognizer:longPress];
}
Para Swift 4, el "func longPress" necesita ser cambiado para que funcione:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// add guesture recognizer
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_:)))
self.button.addGestureRecognizer(longPress)
}
@objc func longPress(_ guesture: UILongPressGestureRecognizer) {
if guesture.state == UIGestureRecognizerState.began {
print("Long Press")
}
}
@IBAction func normalButtonTap(sender: UIButton) {
print("Button tapped")
}
}
Prueba esto:
Agregar botón en viewDidLoad:
como a continuación
-(void)viewDidLoad {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setTag:1]; //you can set any integer value as tag number
btn.title = @"Press Me";
[btn setFrame:CGRectMake(50.0, 50.0, 60.0, 60.0)];
// now create a long press gesture
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressTap:)];
[btn addGestureRecognizer:longPress];
}
Ahora llama al método de gestos como este
-(void)longPressTap:(id)sender {
UIGestureRecognizer *recognizer = (UIGestureRecognizer*) sender
// Recogniser have all property of button on which you have clicked
// Now you can compare button''s tag with recogniser''s view.tag
// View frame for getting the info on which button the click event happened
// Then compare tag like this
if(recognizer.view.tag == 1) {
// Put your button''s click code here
}
// And you can also compare the frame of your button with recogniser''s view
CGRect btnRect = CGRectMake(50.0, 50.0, 60.0, 60.0);
if(recogniser.view.frame == btnRect) {
//put your button''s click code here
}
// Remember frame comparing is alternative method you don''t need to write frame comparing code if you are matching the tag number of button
}
Puede comenzar creando y adjuntando la instancia de UILongPressGestureRecognizer
al botón.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.button addGestureRecognizer:longPress];
[longPress release];
Y luego implementa el método que maneja el gesto
- (void)longPress:(UILongPressGestureRecognizer*)gesture {
if ( gesture.state == UIGestureRecognizerStateEnded ) {
NSLog(@"Long Press");
}
}
Ahora este sería el enfoque básico. También puede establecer la duración mínima de la prensa y la cantidad de error tolerable. Y también tenga en cuenta que el método se llama pocas veces si después de reconocer el gesto, por lo que si desea hacer algo al final del mismo, deberá verificar su estado y manejarlo.
Tengo un UIButton subclase para mi aplicación, así que he retirado mi implementación. Puede agregar esto a su subclase o esto podría ser fácilmente recodificado como una categoría UIButton.
Mi objetivo era agregar la presión prolongada a mi botón sin saturar mis controles de vista con todo el código. Decidí llamar a la acción cuando comienza el estado del reconocedor de gestos.
Hay una advertencia que sale que nunca me he molestado en resolver. Dice que es una posible fuga, pensé que probé el código y no se filtró.
@interface MYLongButton ()
@property (nonatomic, strong) UILongPressGestureRecognizer *gestureRecognizer;
@property (nonatomic, strong) id gestureRecognizerTarget;
@property (nonatomic, assign) SEL gestureRecognizerSelector;
@end
@implementation MYLongButton
- (void)addLongPressTarget:(CGFloat)interval target:(id)target action:(SEL)selector
{
_gestureRecognizerTarget = target;
_gestureRecognizerSelector = selector;
_gestureRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleLongPressGestureRecognizer:)];
_gestureRecognizer.minimumPressDuration = interval;
[self addGestureRecognizer:_gestureRecognizer];
}
- (void)handleLongPressGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
NSAssert([_gestureRecognizerTarget respondsToSelector:_gestureRecognizerSelector], @"target does not respond to selector");
self.highlighted = NO;
// warning on possible leak -- can anybody fix it?
[_gestureRecognizerTarget performSelector:_gestureRecognizerSelector withObject:self];
}
}
Para asignar la acción, agregue esta línea a su método viewDidLoad.
[_myLongButton addLongPressTarget:0.75 target:self selector:@selector(longPressAction:)];
La acción debe definirse como todas las IBAcciones (sin IBAction).
- (void)longPressAction:(id)sender {
// sender is the button
}