Tengo una pregunta sobre UIButton y su área de impacto. Estoy usando el botón Info Dark en el generador de interfaces, pero descubro que el área de impacto no es lo suficientemente grande para los dedos de algunas personas.
¿Hay alguna forma de aumentar el área de pulsación de un botón ya sea mediante programación o en Interface Builder sin cambiar el tamaño del gráfico InfoButton?
ios
cocoa-touch
uibutton
uikit
Kevin Bomberry
fuente
fuente
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return bounds.insetBy(dx: -20, dy: -20).contains(point) }
Respuestas:
Como estoy usando una imagen de fondo, ninguna de estas soluciones funcionó bien para mí. Aquí hay una solución que hace un poco de magia divertida del objetivo-c y ofrece una solución de caída con un código mínimo.
Primero, agregue una categoría
UIButton
que anule la prueba de éxito y también agregue una propiedad para expandir el marco de prueba de éxito.UIButton + Extensiones.h
UIButton + Extensiones.m
Una vez que se agrega esta clase, todo lo que necesita hacer es configurar las inserciones de borde de su botón. Tenga en cuenta que elegí agregar las inserciones, por lo que si desea agrandar el área de impacto, debe usar números negativos.
Nota: Recuerde importar la categoría (
#import "UIButton+Extensions.h"
) en sus clases.fuente
[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"arrow.png"] forState:UIControlStateNormal];
y simplemente establecer el ancho y la altura que necesita: `backButton.frame = CGRectMake (5, 28, 45, 30);`Simplemente configure los valores de inserción del borde de la imagen en el generador de interfaces.
fuente
button.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10);
Aquí hay una solución elegante usando Extensiones en Swift. Le da a todos los UIButtons un área de impacto de al menos 44x44 puntos, según las Pautas de interfaz humana de Apple ( https://developer.apple.com/ios/human-interface-guidelines/visual-design/layout/ )
Swift 2:
Swift 3:
fuente
También podría subclasificar
UIButton
o personalizarUIView
y anularpoint(inside:with:)
con algo como:Swift 3
C objetivo
fuente
Aquí están las extensiones UIButton + de Chase en Swift 3.0.
Para usarlo, puedes:
fuente
UIControl
, noUIButton
.pTouchAreaEdgeInsets
debe serInt
, noUIEdgeInsets
. (En realidad, puede ser de cualquier tipo, peroInt
es el tipo más genérico y simple, por lo que es común en dicha construcción). (Por lo tanto, me encanta este enfoque en general. ¡Gracias, dcRay!)Recomiendo colocar un UIButton con el tipo Personalizado centrado sobre su botón de información. Cambie el tamaño del botón personalizado al tamaño que desea que tenga el área de impacto. A partir de ahí tienes dos opciones:
Marque la opción 'Mostrar toque al resaltar' del botón personalizado. El brillo blanco aparecerá sobre el botón de información, pero en la mayoría de los casos el dedo del usuario cubrirá esto y todo lo que verán es el brillo alrededor del exterior.
Configure un IBOutlet para el botón de información y dos IBActions para el botón personalizado, uno para 'Touch Down' y otro para 'Touch Up Inside'. Luego, en Xcode, haga que el evento de touchdown establezca la propiedad resaltada del botón de información en YES y el evento touchupinside establezca la propiedad resaltada en NO.
fuente
No establezca la
backgroundImage
propiedad con su imagen, establezca laimageView
propiedad. Además, asegúrese de haberimageView.contentMode
establecido enUIViewContentModeCenter
.fuente
imageView.contentMode
se puede configurar comoUIContentModeCenter
.[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
Mi solución en Swift 3:
fuente
No hay nada malo con las respuestas presentadas; sin embargo, quería extender la respuesta de jlarjlar ya que tiene un potencial sorprendente que puede agregar valor al mismo problema con otros controles (por ejemplo, SearchBar). Esto se debe a que ya que pointInside está conectado a una UIView, se puede subclasificar cualquier control para mejorar el área táctil. Esta respuesta también muestra una muestra completa de cómo implementar la solución completa.
Cree una nueva subclase para su botón (o cualquier control)
A continuación, anule el método pointInside en su implementación de subclase
En su archivo de guión gráfico / xib, seleccione el control en cuestión y abra el inspector de identidad y escriba el nombre de su clase personalizada.
En su clase UIViewController para la escena que contiene el botón, cambie el tipo de clase para el botón al nombre de su subclase.
Enlace su storyboard / botón xib a la propiedad IBOutlet y su área táctil se expandirá para adaptarse al área definida en la subclase.
Además de anular el método pointInside junto con los métodos CGRectInset y CGRectContainsPoint , uno debería tomarse un tiempo para examinar CGGeometry para extender el área táctil rectangular de cualquier subclase UIView. También puede encontrar algunos buenos consejos sobre casos de uso de CGGeometry en NSHipster .
Por ejemplo, uno podría hacer que el área táctil sea irregular utilizando los métodos mencionados anteriormente o simplemente elegir hacer que el área táctil de ancho sea dos veces más grande que el área táctil horizontal:
NB: la sustitución de cualquier control de clase UI debería producir resultados similares al extender el área táctil para diferentes controles (o cualquier subclase UIView, como UIImageView, etc.).
fuente
Esto funciona para mi:
fuente
No cambie el comportamiento de UIButton.
fuente
Estoy usando un enfoque más genérico por swizzling
-[UIView pointInside:withEvent:]
. Esto me permite modificar el comportamiento de las pruebas de impacto en cualquieraUIView
, no soloUIButton
.A menudo, se coloca un botón dentro de una vista de contenedor que también limita la prueba de impacto. Por ejemplo, cuando un botón está en la parte superior de una vista de contenedor y desea extender el objetivo táctil hacia arriba, también debe extender el objetivo táctil de la vista de contenedor.
Lo bueno de este enfoque es que puede usar esto incluso en Storyboards agregando un Atributo de tiempo de ejecución definido por el usuario. Por desgracia,
UIEdgeInsets
no está disponible directamente como un tipo allí, pero yaCGRect
también se compone de una estructura con cuatroCGFloat
funciona perfectamente eligiendo "Rect" y rellenar los valores de este tipo:{{top, left}, {bottom, right}}
.fuente
Estoy usando la siguiente clase en Swift, para habilitar también una propiedad de Interface Builder para ajustar el margen:
fuente
Bueno, puede colocar su UIButton dentro de una UIView transparente y ligeramente más grande, y luego capturar los eventos táctiles en la instancia de UIView como en la UIButton. De esa manera, aún tendrá su botón, pero con un área táctil más grande. Tendrá que lidiar manualmente con los estados seleccionados y resaltados con el botón si el usuario toca la vista en lugar del botón.
Otra posibilidad implica usar un UIImage en lugar de un UIButton.
fuente
He podido aumentar el área de impacto del botón de información mediante programación. El gráfico "i" no cambia de escala y permanece centrado en el nuevo marco del botón.
El tamaño del botón de información parece estar fijado a 18x19 [*] en Interface Builder. Al conectarlo a un IBOutlet, pude cambiar su tamaño de cuadro en el código sin ningún problema.
[*]: Parece que las versiones posteriores de iOS han aumentado el área de impacto del botón de información.
fuente
Esta es mi solución Swift 3 (basada en este blog: http://bdunagan.com/2010/03/01/iphone-tip-larger-hit-area-for-uibutton/ )
fuente
Prueba de éxito personalizada de Chase implementada como una subclase de UIButton. Escrito en Objective-C.
Parece que funciona tanto para
init
ybuttonWithType:
constructores. Para mis necesidades es perfecto, pero como la subclasificaciónUIButton
puede ser complicada, me interesaría saber si alguien tiene una falla.CustomeHitAreaButton.h
CustomHitAreaButton.m
fuente
Implementación mediante anulación de UIButton heredado.
Swift 2.2 :
fuente
WJBackgroundInsetButton.h
WJBackgroundInsetButton.m
fuente
Nunca anule el método en la categoría. Botón de subclase y anulación
- pointInside:withEvent:
. Por ejemplo, si el lado de su botón es más pequeño que 44 px (que se recomienda como área mínima tocable) use esto:fuente
Hice una biblioteca para este mismo propósito.
Puede elegir usar una
UIView
categoría, no se requieren subclases :O puede subclasificar su UIView o UIButton y establecer el
minimumHitTestWidth
y / ominimumHitTestHeight
. El área de prueba de acierto de los botones estará representada por estos 2 valores.Al igual que otras soluciones, utiliza el
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
método. Se llama al método cuando iOS realiza pruebas de impacto. Esta publicación de blog tiene una buena descripción de cómo funciona la prueba de impacto de iOS.https://github.com/kgaidis/KGHitTestingViews
También puede subclasificar y usar el Creador de interfaces sin escribir ningún código:
fuente
Base en la respuesta anterior de giaset (que encontré la solución más elegante), aquí está la versión rápida 3:
fuente
Es así de simple:
Eso es todo.
fuente
Estoy usando este truco para el botón dentro de tableviewcell.accessoryView para agrandar su área táctil
fuente
Acabo de hacer el puerto de la solución @Chase en Swift 2.2
y puedes usar así
Para cualquier otra referencia, consulte https://stackoverflow.com/a/13067285/1728552
fuente
Respuesta de @ antoine formateada para Swift 4
fuente
He seguido la respuesta de Chase y funciona muy bien, un solo problema cuando creas el área demasiado grande, más grande que la zona donde el botón se deselecciona (si la zona no era más grande) no llama al selector para el evento UIControlEventTouchUpInside .
Creo que el tamaño es superior a 200 en cualquier dirección o algo así.
fuente
Llegué muy tarde a este juego, pero quería opinar sobre una técnica simple que podría resolver sus problemas. Aquí hay un fragmento programático típico de UIButton para mí:
Estoy cargando una imagen png transparente para mi botón y estableciendo la imagen de fondo. Estoy configurando el marco basado en el UIImage y escalando un 50% para la retina. OK, tal vez estés de acuerdo con lo anterior o no, PERO si quieres hacer que el área de golpe sea MÁS GRANDE y ahorrarte un dolor de cabeza:
Lo que hago es abrir la imagen en Photoshop y simplemente aumentar el tamaño del lienzo al 120% y guardar. Efectivamente, acaba de agrandar la imagen con píxeles transparentes.
Solo un enfoque.
fuente
La respuesta de @jlajlar anterior parecía buena y directa, pero no coincide con Xamarin.iOS, así que la convertí en Xamarin. Si está buscando una solución en un iOS de Xamarin, aquí está:
Puede agregar este método a la clase donde está anulando UIView o UIImageView. Esto funcionó muy bien :)
fuente
Ninguna de las respuestas funciona perfectamente para mí, porque uso la imagen de fondo y un título en ese botón. Además, el botón cambiará de tamaño a medida que cambie el tamaño de la pantalla.
En cambio, agrando el área del grifo haciendo que el área transparente PNG sea más grande.
fuente