J'ai une question concernant UIButton et sa zone touchée. J'utilise le bouton Info Dark dans le générateur d'interface, mais je constate que la zone de frappe n'est pas assez grande pour les doigts de certaines personnes.
Existe-t-il un moyen d'augmenter la zone de sélection d'un bouton par programme ou dans Interface Builder sans modifier la taille du graphique InfoButton?
ios
cocoa-touch
uibutton
uikit
Kevin Bomberry
la source
la source
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return bounds.insetBy(dx: -20, dy: -20).contains(point) }
Réponses:
Puisque j'utilise une image d'arrière-plan, aucune de ces solutions n'a bien fonctionné pour moi. Voici une solution qui fait de la magie objective-c amusante et offre une solution de remplacement avec un code minimal.
Tout d'abord, ajoutez une catégorie à
UIButton
celle qui remplace le test de positionnement et ajoute également une propriété pour développer le cadre de test de positionnement.UIButton + Extensions.h
UIButton + Extensions.m
Une fois cette classe ajoutée, tout ce que vous avez à faire est de définir les encarts de bord de votre bouton. Notez que j'ai choisi d'ajouter les encarts, donc si vous voulez agrandir la zone de frappe, vous devez utiliser des nombres négatifs.
Remarque: n'oubliez pas d'importer la catégorie (
#import "UIButton+Extensions.h"
) dans vos classes.la source
[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"arrow.png"] forState:UIControlStateNormal];
Et définissez simplement la largeur et la hauteur dont vous avez besoin: `backButton.frame = CGRectMake (5, 28, 45, 30);`Définissez simplement les valeurs d'encart de bord de l'image dans le générateur d'interface.
la source
button.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10);
Voici une solution élégante utilisant les extensions dans Swift. Il donne à tous les UIButtons une zone de frappe d'au moins 44x44 points, conformément aux directives d'interface humaine d'Apple ( https://developer.apple.com/ios/human-interface-guidelines/visual-design/layout/ )
Swift 2:
Swift 3:
la source
Vous pouvez également sous
UIButton
- classe ou une coutumeUIView
et remplacerpoint(inside:with:)
avec quelque chose comme:Swift 3
Objectif c
la source
Voici les extensions UIButton + de Chase dans Swift 3.0.
Pour l'utiliser, vous pouvez:
la source
UIControl
, nonUIButton
.pTouchAreaEdgeInsets
doit êtreInt
, nonUIEdgeInsets
. (En fait, il peut s'agir de n'importe quel type, maisInt
c'est le type le plus générique et le plus simple, il est donc courant dans une telle construction). (Par conséquent, j'adore cette approche en général. Merci, dcRay!)Je recommande de placer un UIButton avec le type Personnalisé centré sur votre bouton d'information. Redimensionnez le bouton personnalisé à la taille souhaitée pour la zone de frappe. De là, vous avez deux options:
Cochez l'option «Afficher le toucher en surbrillance» du bouton personnalisé. La lueur blanche apparaîtra sur le bouton d'information, mais dans la plupart des cas, le doigt de l'utilisateur couvrira cela et tout ce qu'ils verront, c'est la lueur autour de l'extérieur.
Configurez un IBOutlet pour le bouton info et deux IBActions pour le bouton personnalisé, un pour «Touch Down» et un pour «Touch Up Inside». Ensuite, dans Xcode, faites en sorte que l'événement touchdown définisse la propriété en surbrillance du bouton d'information sur YES et que l'événement touchupinside définisse la propriété en surbrillance sur NON.
la source
Ne définissez pas la
backgroundImage
propriété avec votre image, définissez laimageView
propriété. Assurez-vous également que vous avezimageView.contentMode
défini surUIViewContentModeCenter
.la source
imageView.contentMode
peut être défini commeUIContentModeCenter
.[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
Ma solution sur Swift 3:
la source
Il n'y a rien de mal avec les réponses présentées; Cependant, je voulais étendre la réponse de jlarjlar car elle possède un potentiel incroyable qui peut ajouter de la valeur au même problème avec d'autres contrôles (par exemple, SearchBar). En effet, puisque pointInside est attaché à un UIView, il est possible de sous-classer n'importe quel contrôle pour améliorer la zone tactile. Cette réponse montre également un exemple complet de mise en œuvre de la solution complète.
Créez une nouvelle sous-classe pour votre bouton (ou tout contrôle)
Remplacez ensuite la méthode pointInside dans votre implémentation de sous-classe
Sur votre fichier storyboard / xib, sélectionnez le contrôle en question et ouvrez l'inspecteur d'identité et tapez le nom de votre classe personnalisée.
Dans votre classe UIViewController pour la scène contenant le bouton, remplacez le type de classe du bouton par le nom de votre sous-classe.
Liez votre bouton storyboard / xib à la propriété IBOutlet et votre zone tactile sera étendue pour s'adapter à la zone définie dans la sous-classe.
En plus de remplacer la méthode pointInside avec les méthodes CGRectInset et CGRectContainsPoint , il faut prendre le temps d'examiner la CGGeometry pour étendre la zone tactile rectangulaire de toute sous-classe UIView. Vous pouvez également trouver de bons conseils sur les cas d'utilisation de CGGeometry sur NSHipster .
Par exemple, on pourrait rendre la zone tactile irrégulière en utilisant les méthodes mentionnées ci-dessus ou simplement choisir de rendre la zone tactile de largeur deux fois plus grande que la zone tactile horizontale:
NB: la substitution de n'importe quel contrôle de classe d'interface utilisateur devrait produire des résultats similaires en étendant la zone tactile pour différents contrôles (ou toute sous-classe UIView, comme UIImageView, etc.).
la source
Cela fonctionne pour moi:
la source
Ne changez pas le comportement d'UIButton.
la source
J'utilise une approche plus générique en swizzling
-[UIView pointInside:withEvent:]
. Cela me permet de modifier le comportement de test de recherche sur toutUIView
, pas seulementUIButton
.Souvent, un bouton est placé dans une vue de conteneur qui limite également le test de positionnement. Par exemple, lorsqu'un bouton se trouve en haut d'une vue de conteneur et que vous souhaitez étendre la cible tactile vers le haut, vous devez également étendre la cible tactile de la vue de conteneur.
La bonne chose à propos de cette approche est que vous pouvez l'utiliser même dans les storyboards en ajoutant un attribut d'exécution défini par l'utilisateur. Malheureusement,
UIEdgeInsets
n'est pas directement disponible en tant que type là , mais depuis seCGRect
compose également d'une struct avec quatreCGFloat
il fonctionne parfaitement en choisissant « Rect » et remplir les valeurs comme ceci:{{top, left}, {bottom, right}}
.la source
J'utilise la classe suivante dans Swift, pour activer également une propriété Interface Builder pour ajuster la marge:
la source
Eh bien, vous pouvez placer votre UIButton dans un UIView transparent et légèrement plus grand, puis capturer les événements tactiles sur l'instance UIView comme dans UIButton. De cette façon, vous aurez toujours votre bouton, mais avec une zone tactile plus grande. Vous devrez gérer manuellement les états sélectionnés et mis en évidence avec le bouton si l'utilisateur touche la vue au lieu du bouton.
Une autre possibilité consiste à utiliser une UIImage au lieu d'un UIButton.
la source
J'ai pu augmenter la zone de frappe du bouton info par programmation. Le graphique "i" ne change pas d'échelle et reste centré dans le nouveau cadre du bouton.
La taille du bouton info semble être fixée à 18x19 [*] dans Interface Builder. En le connectant à un IBOutlet, j'ai pu modifier sa taille d'image dans le code sans aucun problème.
[*]: Les versions ultérieures d'iOS semblent avoir augmenté la zone d'accès du bouton d'information.
la source
Ceci est ma solution Swift 3 (basée sur cet article de blog: http://bdunagan.com/2010/03/01/iphone-tip-larger-hit-area-for-uibutton/ )
la source
Le test de succès personnalisé de Chase implémenté en tant que sous-classe d'UIButton. Écrit en Objective-C.
Cela semble fonctionner à la fois pour
init
et pour lesbuttonWithType:
constructeurs. Pour mes besoins, c'est parfait, mais comme le sous-classementUIButton
peut être poilu, je serais intéressé de savoir si quelqu'un a un problème avec cela.CustomeHitAreaButton.h
CustomHitAreaButton.m
la source
Implémentation par remplacement hérité d'UIButton.
Swift 2.2 :
la source
WJBackgroundInsetButton.h
WJBackgroundInsetButton.m
la source
Ne remplacez jamais la méthode dans la catégorie. Bouton de sous-classe et remplacement
- pointInside:withEvent:
. Par exemple, si le côté de votre bouton est inférieur à 44 px (ce qui est recommandé comme zone d'appui minimale), utilisez ceci:la source
J'ai créé une bibliothèque dans ce but précis.
Vous pouvez choisir d'utiliser une
UIView
catégorie, aucune sous-classification n'est requise :Ou vous pouvez sous-classer votre UIView ou UIButton et définir le
minimumHitTestWidth
et / ouminimumHitTestHeight
. Votre zone de test de frappe de bouton sera alors représentée par ces 2 valeurs.Tout comme les autres solutions, il utilise la
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
méthode. La méthode est appelée lorsque iOS effectue un test de positionnement. Cet article de blog a une bonne description du fonctionnement des tests de succès iOS.https://github.com/kgaidis/KGHitTestingViews
Vous pouvez également simplement sous-classer et utiliser Interface Builder sans écrire de code:
la source
Sur la base de la réponse de giaset ci-dessus (dont j'ai trouvé la solution la plus élégante), voici la version swift 3:
la source
C'est aussi simple que ça:
C'est tout ça.
la source
J'utilise cette astuce pour le bouton à l'intérieur de tableviewcell.accessoryView pour agrandir sa zone tactile
la source
Je viens de faire le portage de la solution @Chase dans swift 2.2
un vous pouvez utiliser comme ça
Pour toute autre référence, voir https://stackoverflow.com/a/13067285/1728552
la source
Réponse de @ antoine formatée pour Swift 4
la source
J'ai suivi la réponse de Chase et cela fonctionne très bien, un seul problème lorsque vous créez une arrea trop grande, plus grande que la zone où le bouton est désélectionné (si la zone n'était pas plus grande), il n'appelle pas le sélecteur pour l'événement UIControlEventTouchUpInside .
Je pense que la taille est supérieure à 200 dans n'importe quelle direction ou quelque chose comme ça.
la source
Je suis si en retard à ce jeu, mais je voulais peser sur une technique simple qui pourrait résoudre vos problèmes. Voici un extrait de code UIButton programmatique typique pour moi:
Je charge une image png transparente pour mon bouton et je règle l'image d'arrière-plan. Je suis en train de définir le cadre en fonction de l'UIImage et de le mettre à l'échelle de 50% pour la rétine. OK, peut-être êtes-vous d'accord avec ce qui précède ou non, MAIS si vous voulez agrandir la zone de frappe et vous épargner un mal de tête:
Ce que je fais, ouvrez l'image dans Photoshop et augmentez simplement la taille de la toile à 120% et économisez. En fait, vous venez d'agrandir l'image avec des pixels transparents.
Juste une approche.
la source
La réponse de @jlajlar ci-dessus semblait bonne et simple mais ne correspond pas à Xamarin.iOS, je l'ai donc convertie en Xamarin. Si vous recherchez une solution sur un iOS Xamarin, la voici:
Vous pouvez ajouter cette méthode à la classe dans laquelle vous substituez UIView ou UIImageView. Cela a bien fonctionné :)
la source
Aucune des réponses ne fonctionne parfaitement pour moi, car j'utilise une image d'arrière-plan et un titre sur ce bouton. De plus, le bouton se redimensionnera à mesure que la taille de l'écran change.
Au lieu de cela, j'agrandit la zone du robinet en agrandissant la zone transparente png.
la source