iphone - framework - UIButton dentro de una vista que tiene un UITapGestureRecognizer
objective c vs swift (11)
Si su escenario es así:
Tiene una vista simple y algunos UIButtons, los controles UITextField agregados como subvistas a esa vista. Ahora quiere cerrar el teclado cuando toca en cualquier otro lugar de la vista, excepto en los controles (subvistas que ha agregado)
Entonces la solución es:
Agregue el siguiente método a su XYZViewController.m (que tiene su vista)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
Tengo una vista con un UITapGestureRecognizer
. Entonces, cuando toco en la vista, aparece otra vista encima de esta vista. Esta nueva vista tiene tres botones. Cuando presiono uno de estos botones no obtengo la acción de los botones, solo obtengo la acción de tocar el gesto. Así que ya no puedo usar estos botones. ¿Qué puedo hacer para llevar los eventos a estos botones? Lo extraño es que los botones siguen resaltados.
No puedo simplemente quitar el UITAPGestureRecognizer después de recibir su toque. Porque con esto, la nueva vista también puede eliminarse. Significa que quiero un comportamiento como los controles de pantalla completa .
Aquí está la versión rápida de la respuesta de Kevin Ballard que funcionó para mí:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if (scrollView.superview != nil) {
if ((touch.view?.isDescendantOfView(scrollView)) != nil) { return false }
}
return true
}
Como continuación de la respuesta de Kevin Ballard, tuve el mismo problema y terminé usando este código:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIButton class]]){
return NO;
}
return YES;
}
Tiene el mismo efecto, pero funcionará en cualquier UIButton a cualquier profundidad de vista (mi UIButton tenía varias vistas de profundidad y el delegado de UIGestureRecognizer no tenía una referencia).
Como seguimiento del seguimiento de Casey a la respuesta de Kevin Ballard:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIControl class]]) {
// we touched a button, slider, or other UIControl
return NO; // ignore the touch
}
return YES; // handle the touch
}
Esto básicamente hace que todos los tipos de controles de entrada de usuario como botones, controles deslizantes, etc. funcionen
En iOS 6.0 y versiones posteriores, las acciones de control predeterminadas evitan la superposición del comportamiento del reconocedor de gestos. Por ejemplo, la acción predeterminada para un botón es un solo toque. Si tiene un solo reconocedor de toque asociado a la vista principal de un botón, y el usuario toca el botón, el método de acción del botón recibe el evento táctil en lugar del reconocedor de gestos. Esto se aplica solo al reconocimiento de gestos que se superpone a la acción predeterminada para un control, que incluye: .....
Encontré esta respuesta aquí: link
También puedes usar
tapRecognizer.cancelsTouchesInView = NO;
Lo que impide que el reconocedor de tap sea el único que atrape todos los grifos
ACTUALIZACIÓN: Michael mencionó el enlace a la documentación que describe esta propiedad: cancelsTouchesInView
Encontré otra manera de hacerlo desde here . Detecta el toque ya sea dentro de cada botón o no.
(1) pointInside:withEvent: (2) locationInView:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch {
// Don''t recognize taps in the buttons
return (![self.button1 pointInside:[touch locationInView:self.button1] withEvent:nil] &&
![self.button2 pointInside:[touch locationInView:self.button2] withEvent:nil] &&
![self.button3 pointInside:[touch locationInView:self.button3] withEvent:nil]);
}
Estas respuestas fueron incompletas. Tuve que leer varias publicaciones sobre cómo usar esta operación booleana.
En su archivo * .h, agregue esto
@interface v1ViewController : UIViewController <UIGestureRecognizerDelegate>
En su archivo * .m, agregue esto
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
NSLog(@"went here ...");
if ([touch.view isKindOfClass:[UIControl class]])
{
// we touched a button, slider, or other UIControl
return NO; // ignore the touch
}
return YES; // handle the touch
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//tap gestrure
UITapGestureRecognizer *tapGestRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenTappedOnce)];
[tapGestRecog setNumberOfTapsRequired:1];
[self.view addGestureRecognizer:tapGestRecog];
// This line is very important. if You don''t add it then your boolean operation will never get called
tapGestRecog.delegate = self;
}
-(IBAction) screenTappedOnce
{
NSLog(@"screenTappedOnce ...");
}
Optimizando la respuesta de @ cdasher, obtienes
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
{
return ![touch.view isKindOfClass:[UIControl class]];
}
Puede configurar su controlador o ver (lo que crea el reconocedor de gestos) como el delegado de UITapGestureRecognizer
. Luego, en el delegado puede implementar -gestureRecognizer:shouldReceiveTouch:
En su implementación, puede probar si el toque pertenece a su nueva subvista, y si lo hace, solicite al reconocedor de gestos que la ignore. Algo como lo siguiente:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// test if our control subview is on-screen
if (self.controlSubview.superview != nil) {
if ([touch.view isDescendantOfView:self.controlSubview]) {
// we touched our control surface
return NO; // ignore the touch
}
}
return YES; // handle the touch
}
Puede detener la UITAPGestureRecognizer para que no cancele otros eventos (como tocar el botón) configurando el siguiente booleano:
[tapRecognizer setCancelsTouchesInView:NO];