UIButton: Rendre le coup plus que la superficie par défaut de la zone frappée par le
J'ai une question à traiter avec UIButton et son hit de la zone. Je suis à l'aide de l'Info bouton Sombre dans interface builder, mais je trouve que le coup de la zone n'est pas assez grand pour certaines personnes, l'doigts.
Est-il un moyen pour augmenter la zone frappée par un bouton par programmation ou dans Interface Builder, sans modification de la taille de la InfoButton graphique?
- Si rien ne fonctionne, il suffit d'ajouter un UIButton sans une image, puis de mettre une ImageView de superposition !
- Ce serait le plus étonnamment simple question sur l'ensemble du site, qui a des dizaines de réponses. Je veux dire, je peux coller l'intégralité de la réponse ici:
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return bounds.insetBy(dx: -20, dy: -20).contains(point) }
Vous devez vous connecter pour publier un commentaire.
Depuis que je suis en utilisant une image de fond, aucune de ces solutions a bien fonctionné pour moi. Voici une solution qui ne prend du plaisir objective-c la magie et offre une goutte dans une solution avec un minimum de code.
Tout d'abord, ajoutez un catégorie à
UIButton
qui remplace le test de collision et ajoute également une propriété pour l'expansion de la frapper cadre de test.UIButton+Extensions.h
UIButton+Extensions.m
Une fois cette classe est ajouté, tout ce que vous devez faire est de régler le bord des encarts de votre bouton. Notez que j'ai choisi d'ajouter des encarts donc, si vous voulez faire de la zone frappée par le plus grand, vous devez utiliser des nombres négatifs.
Remarque: n'oubliez pas d'importer la catégorie (
#import "UIButton+Extensions.h"
) dans vos classes.[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"arrow.png"] forState:UIControlStateNormal];
Et juste définir la largeur & hauteur dont vous avez besoin:` backButton.frame = CGRectMake(5, 28, 45, 30);`Juste mis en bords de l'image, les valeurs des encarts dans interface builder.
button.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10);
Voici une solution élégante à l'aide des Extensions de Swift. Il donne à tous les UIButtons une zone frappée par au moins 44x44 points, comme par Apple Human Interface Guidelines (https://developer.apple.com/ios/human-interface-guidelines/visual-design/layout/)
Swift 2:
Swift 3:
Vous pouvez également sous-classe
UIButton
ou personnaliséUIView
et remplacerpoint(inside:with:)
avec quelque chose comme:Swift 3
Objective-C
Voici Chase UIButton+Extensions Swift 3.0.
Pour l'utiliser, vous pouvez:
UIControl
, pasUIButton
.pTouchAreaEdgeInsets
doit êtreInt
, pasUIEdgeInsets
. (En fait, ça peut être n'importe quel type, maisInt
est le plus générique et simple, de sorte qu'il est commun dans cette construction). (Donc j'aime cette approche en général. Merci, dcRay!)Ne réglez pas le
backgroundImage
bien avec votre image, mettez leimageView
de la propriété. Aussi, assurez-vous d'avoirimageView.contentMode
fixé àUIViewContentModeCenter
.imageView.contentMode
peut être définie commeUIContentModeCenter
.[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
Je recommande de placer un UIButton avec le type Personnalisé centré sur votre bouton info. Redimensionner le bouton personnalisé à la taille que vous voulez le frapper domaine de l'être. À partir de là, vous avez deux options:
Cochez la case " Afficher le toucher de la surbrillance l'option du bouton personnalisé. La lueur blanche apparaît sur le bouton info, mais dans la plupart des cas, les utilisateurs doigt couvre ce et tout ce qu'ils vont voir, c'est la lueur autour de l'extérieur.
Configurer un IBOutlet pour la touche info et deux IBActions pour le bouton personnalisé pour un "Touch Down" et une pour la "Touche Jusqu'à l'Intérieur". Puis dans Xcode faire de l'événement touchdown ensemble de la propriété en surbrillance le bouton info pour OUI et le touchupinside événement définissez la propriété sélectionnée ou PAS.
Ma solution sur Swift 3:
Il n'y a rien de mal avec les réponses présentées; cependant j'ai voulu prolonger jlarjlar réponse car il recèle un potentiel étonnant qui peut ajouter de la valeur pour le même problème avec d'autres contrôles (par exemple barre de recherche). C'est parce que depuis pointInside est attaché à une UIView, on est capable de la sous-classe aucun contrôle pour améliorer la zone tactile. Cette réponse montre un échantillon complet de la façon de mettre en œuvre la solution complète.
Créer une nouvelle sous-classe de votre bouton (ou tout contrôle)
Prochaine remplacer la pointInside méthode dans votre sous-classe de mise en œuvre
Sur votre table de montage séquentiel/xib fichier, sélectionnez la commande en question et d'ouvrir l'identité de l'inspecteur et tapez le nom de votre classe personnalisée.
Dans votre classe UIViewController pour la scène contenant le bouton modifier le type de classe pour le bouton sur le nom de votre sous-classe.
Lien de votre table de montage séquentiel/xib bouton de la propriété IBOutlet et votre zone tactile sera élargi pour s'adapter à la zone définie dans la sous-classe.
En plus à la redéfinition de la pointInside méthode avec le CGRectInset et CGRectContainsPoint méthodes, il faut prendre le temps d'examiner les CGGeometry pour l'extension de la rectangulaires zone tactile de toute sous-classe UIView. Vous pouvez aussi trouver des conseils sympas sur CGGeometry cas d'utilisation à NSHipster.
Par exemple on pourrait faire de la zone tactile irrégulière en utilisant les méthodes mentionnées ci-dessus ou tout simplement choisir de faire de la largeur de la zone de toucher deux fois plus grand que l'horizontale de la zone tactile:
NB: la Substitution de toute INTERFACE de commande de Classe doit produire des résultats similaires sur l'extension de la zone tactile pour les différents contrôles (ou tout sous-classe UIView, comme UIImageView, etc).
Cela fonctionne pour moi:
De ne pas changer le comportement de UIButton.
Je suis en utilisant une approche plus générique par swizzling
-[UIView pointInside:withEvent:]
. Cela me permet de modifier frapper les tests de comportement sur toutUIView
, pas seulementUIButton
.Souvent, un bouton est placé à l'intérieur d'un conteneur de vue qui limite également le coup d'essais. Par exemple, lorsqu'un bouton est en haut d'un conteneur en vue et que vous souhaitez prolonger la cible tactile vers le haut, vous avez également de prolonger la cible tactile du conteneur de vue.
La bonne chose à propos de cette approche est que vous pouvez utiliser ce même dans les Storyboards par l'ajout d'un Utilisateur Défini Exécution de l'Attribut. Malheureusement,
UIEdgeInsets
n'est pas directement disponible en tant que type de il y mais depuisCGRect
se compose également d'une structure avec quatreCGFloat
il fonctionne parfaitement en choisissant "Rect" et en remplissant les valeurs comme ceci:{{top, left}, {bottom, right}}
.Bien, vous pouvez placer votre UIButton à l'intérieur d'un transparent et un peu plus grand UIView, et ensuite de prendre les événements tactiles sur le UIView exemple comme dans le UIButton. De cette façon, vous aurez toujours votre bouton, mais avec une plus grande zone tactile. Vous manuellement avoir à traiter avec une sélection de & souligné les etats con le bouton si l'utilisateur touche la vue au lieu de la touche.
Autre possibilité consiste à utiliser une UIImage au lieu d'un UIButton.
J'ai été en mesure d'augmenter le hit de la zone de la touche info de la programmation. Le "je" graphique n'a pas changer d'échelle et reste centrée dans la nouvelle image du bouton.
La taille de la touche info semble être fixé à 18x19[*] dans Interface Builder. En le connectant à un IBOutlet, j'ai été en mesure de changer la taille de l'image dans le code, sans aucun problème.
[*]: Plus tard, les versions de l'iOS semblent avoir augmenté le coup de la zone de la touche info.
Je suis en utilisant la classe suivante dans Swift, également activer une Interface Builder propriété pour ajuster la marge:
C'est mon Swift 3 Solution(basé sur ce blog: http://bdunagan.com/2010/03/01/iphone-tip-larger-hit-area-for-uibutton/)
Chase d'accès personnalisé test mis en œuvre comme une sous-classe de UIButton. Écrit en Objective-C.
Il semble fonctionner à la fois pour
init
etbuttonWithType:
constructeurs. Pour mes besoins c'est parfait, mais depuis le sous-classementUIButton
peut être poilu, je serais curieux de savoir si quelqu'un a un problème avec elle.CustomeHitAreaButton.h
CustomHitAreaButton.m
Mise en œuvre par le biais de remplacer hérité UIButton.
Swift 2.2:
WJBackgroundInsetButton.h
WJBackgroundInsetButton.m
Jamais remplacer la méthode dans la catégorie. Sous-classe bouton et remplacer
- pointInside:withEvent:
. Par exemple, si votre bouton est plus petit que 44 px (ce qui est recommandé comme minimum tappable area), utilisez ceci:J'ai fait un bibliothèque à cet effet.
Vous pouvez choisir d'utiliser un
UIView
catégorie, pas de sous-classement requis:Ou vous pouvez votre sous-classe UIView ou UIButton et définir la
minimumHitTestWidth
et/ouminimumHitTestHeight
. Votre bouton hit-zone de test sera alors représenté par ces 2 valeurs.À l'instar d'autres solutions, il utilise le
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
méthode. La méthode est appelée lors de l'iOS effectue le test d'atteinte. Cette blog a une bonne description sur comment iOS hit-travaux d'essais.https://github.com/kgaidis/KGHitTestingViews
Vous pouvez aussi simplement sous-classe et à utiliser Interface Builder sans écrire de code:

Base sur giaset la réponse ci-dessus (que j'ai trouvé la solution la plus élégante), voici la swift 3 version:
Je vais utiliser cette astuce pour bouton à l'intérieur de tableviewcell.accessoryView pour agrandir sa zone tactile
J'ai juste fait le port de la @Chase solution dans swift 2.2
un que vous pouvez utiliser comme cette
Pour toute autre référence, voir https://stackoverflow.com/a/13067285/1728552
@antoine réponse formatée pour Swift 4
J'ai suivi Chase de réponse et il fonctionne très bien, seul problème lorsque vous créez le arrea trop grand, plus grand que la zone où le bouton obtient désactivée (si la zone n'était pas plus gros) il ne demande pas le sélecteur de UIControlEventTouchUpInside événement.
Je pense que la taille est de plus de 200 importe quelle direction ou quelque chose comme ça.
Je suis en retard pour ce jeu, mais je voulais peser sur une technique simple qui pourrait résoudre votre problèmes. Voici un exemple typique d'programmatique UIButton extrait pour moi:
Je suis le chargement d'une Image au format png transparent pour mon bouton et le réglage de l'image d'arrière-plan. Je suis réglage de l'image basée sur la UIImage et de mise à l'échelle de 50% pour la rétine. OK, peut-être que vous êtes d'accord avec ce qui précède ou pas, MAIS si vous voulez faire de la zone frappée par le PLUS grand et vous épargner les maux de tête:
Ce que je fais, ouvrez l'image dans photoshop et simplement augmenter la taille du canevas à 120% et économisez. Effectivement tu viens de faire l'image de l'ampleur avec les pixels transparents.
Qu'une démarche.
@jlajlar 's réponse ci-dessus semble être bonne et simple mais ne correspond pas à Xamarin.iOS, donc j'ai converti en Xamarin.
Si vous à la recherche d'une solution sur un Xamarin iOS, il y a ici, il va:
Vous pouvez ajouter cette méthode à la classe où vous écrasez UIView ou UIImageView. Cela fonctionnait bien 🙂
Aucune réponse fonctionne parfaitement pour moi, parce que je utiliser l'image de fond et un titre sur ce bouton. En outre, le bouton redimensionner, selon la taille de l'écran change.
Au lieu de cela, je agrandir appuyez sur la zone en faisant le png transparent zone plus grande.
Cette Swift version vous permet de définir un minimum de frapper de taille pour tous les UIButtons. Surtout, il gère également le cas lorsque UIButtons sont cachés, qui beaucoup de réponses de la négligence.
Similaire à Zhanserik, avec la variable d'extension et de mise à jour pour Swift 4.2:
C'est juste ce simple:
Que la chose entière.
Swift:
De mon point de vue: