Ich habe eine Frage zu UIButton und seinem Trefferbereich. Ich verwende die Schaltfläche "Info Dark" im Interface Builder, stelle jedoch fest, dass der Trefferbereich nicht groß genug für die Finger einiger Personen ist.
Gibt es eine Möglichkeit, die Trefferfläche einer Schaltfläche entweder programmgesteuert oder im Interface Builder zu vergrößern, ohne die Größe der InfoButton-Grafik zu ändern?
ios
cocoa-touch
uibutton
uikit
Kevin Bomberry
quelle
quelle
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return bounds.insetBy(dx: -20, dy: -20).contains(point) }
Antworten:
Da ich ein Hintergrundbild verwende, hat keine dieser Lösungen für mich gut funktioniert. Hier ist eine Lösung, die Spaß macht und eine Drop-In-Lösung mit minimalem Code bietet.
Fügen Sie zunächst eine Kategorie hinzu
UIButton
, die den Treffer-Test überschreibt, und fügen Sie eine Eigenschaft zum Erweitern des Treffer-Test-Frames hinzu.UIButton + Extensions.h
UIButton + Extensions.m
Sobald diese Klasse hinzugefügt wurde, müssen Sie nur noch die Kanteneinfügungen Ihrer Schaltfläche festlegen. Beachten Sie, dass ich die Einfügungen hinzugefügt habe. Wenn Sie also die Trefferfläche vergrößern möchten, müssen Sie negative Zahlen verwenden.
Hinweis: Denken Sie daran, die Kategorie (
#import "UIButton+Extensions.h"
) in Ihre Klassen zu importieren .quelle
[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"arrow.png"] forState:UIControlStateNormal];
Wenn Sie zu viel unnötige Arbeit leisten, können Sie zwei einfache Codezeilen ausführen: Stellen Sie einfach die Breite und Höhe ein, die Sie benötigen: `backButton.frame = CGRectMake (5, 28, 45, 30);`Legen Sie einfach die Werte für die Bildkanteneinfügung im Interface Builder fest.
quelle
button.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10);
Hier ist eine elegante Lösung mit Extensions in Swift. Es gibt allen UIButtons einen Trefferbereich von mindestens 44 x 44 Punkten gemäß den Richtlinien für die Benutzeroberfläche von Apple ( https://developer.apple.com/ios/human-interface-guidelines/visual-design/layout/ ).
Swift 2:
Swift 3:
quelle
Sie können auch eine Unterklasse
UIButton
oder einen BenutzerUIView
festlegen und Folgendes überschreibenpoint(inside:with:)
:Swift 3
Ziel c
quelle
Hier ist Chases UIButton + Extensions in Swift 3.0.
Um es zu verwenden, können Sie:
quelle
UIControl
, nichtUIButton
.pTouchAreaEdgeInsets
mussInt
nicht seinUIEdgeInsets
. (Eigentlich kann es jeder Typ sein, aber esInt
ist der allgemeinste und einfachste Typ, daher ist er bei solchen Konstruktionen üblich). (Deshalb liebe ich diesen Ansatz im Allgemeinen. Danke, dcRay!)Ich empfehle, einen UIButton mit dem Typ Benutzerdefiniert über Ihrer Info-Schaltfläche zu platzieren. Ändern Sie die Größe der benutzerdefinierten Schaltfläche auf die Größe, die der Trefferbereich haben soll. Von dort haben Sie zwei Möglichkeiten:
Aktivieren Sie die Option "Touch-on-Highlight anzeigen" der benutzerdefinierten Schaltfläche. Das weiße Leuchten erscheint über der Info-Schaltfläche, aber in den meisten Fällen deckt der Finger des Benutzers dies ab und alles, was er sieht, ist das Leuchten um die Außenseite.
Richten Sie ein IBOutlet für die Info-Schaltfläche und zwei IBActions für die benutzerdefinierte Schaltfläche ein, eine für 'Touch Down' und eine für 'Touch Up Inside'. Stellen Sie dann in Xcode das Touchdown-Ereignis ein, setzen Sie die hervorgehobene Eigenschaft der Info-Schaltfläche auf YES, und das touchupinside-Ereignis setzt die hervorgehobene Eigenschaft auf NO.
quelle
Legen Sie die
backgroundImage
Eigenschaft nicht mit Ihrem Bild fest, sondern legen Sie sie festimageView
. Also, stellen Sie sicher , dass SieimageView.contentMode
setzen aufUIViewContentModeCenter
.quelle
imageView.contentMode
kann eingestellt werden alsUIContentModeCenter
.[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
Meine Lösung für Swift 3:
quelle
An den Antworten ist nichts auszusetzen. Ich wollte jedoch die Antwort von jlarjlar erweitern, da sie ein erstaunliches Potenzial birgt, das das gleiche Problem mit anderen Steuerelementen (z. B. SearchBar) aufwerten kann. Dies liegt daran, dass pointInside an eine UIView angehängt ist und jedes Steuerelement in Unterklassen unterteilt werden kann , um den Berührungsbereich zu verbessern. Diese Antwort zeigt auch ein vollständiges Beispiel für die Implementierung der vollständigen Lösung.
Erstellen Sie eine neue Unterklasse für Ihre Schaltfläche (oder ein beliebiges Steuerelement).
Überschreiben Sie als Nächstes die pointInside-Methode in Ihrer Unterklassenimplementierung
Wählen Sie in Ihrer Storyboard- / XIB-Datei das betreffende Steuerelement aus, öffnen Sie den Identitätsinspektor und geben Sie den Namen Ihrer benutzerdefinierten Klasse ein.
Ändern Sie in Ihrer UIViewController-Klasse für Szenen, die die Schaltfläche enthalten, den Klassentyp für die Schaltfläche in den Namen Ihrer Unterklasse.
Verknüpfen Sie Ihre Storyboard- / XIB-Schaltfläche mit der Eigenschaft IBOutlet, und Ihr Touch-Bereich wird erweitert, um dem in der Unterklasse definierten Bereich zu entsprechen.
Zusätzlich zum Überschreiben der pointInside-Methode zusammen mit den Methoden CGRectInset und CGRectContainsPoint sollte man sich Zeit nehmen, um die CGGeometry auf die Erweiterung des rechteckigen Berührungsbereichs einer UIView-Unterklasse zu untersuchen. Möglicherweise finden Sie auch einige nützliche Tipps zu CGGeometry-Anwendungsfällen bei NSHipster .
Zum Beispiel könnte man den Berührungsbereich mit den oben genannten Methoden unregelmäßig machen oder einfach wählen, den Breiten-Berührungsbereich doppelt so groß wie den horizontalen Berührungsbereich zu machen:
Hinweis: Das Ersetzen eines UI-Klassensteuerelements sollte zu ähnlichen Ergebnissen führen, wenn der Berührungsbereich für verschiedene Steuerelemente (oder eine UIView-Unterklasse wie UIImageView usw.) erweitert wird.
quelle
Das funktioniert bei mir:
quelle
Ändern Sie nicht das Verhalten von UIButton.
quelle
Ich benutze einen allgemeineren Ansatz durch Swizzling
-[UIView pointInside:withEvent:]
. Auf diese Weise kann ich das Verhalten beim Testen von Treffern ändernUIView
, nicht nurUIButton
.Oft wird eine Schaltfläche in einer Containeransicht platziert, die auch die Trefferprüfung einschränkt. Wenn sich beispielsweise eine Schaltfläche oben in einer Containeransicht befindet und Sie das Berührungsziel nach oben erweitern möchten, müssen Sie auch das Berührungsziel der Containeransicht erweitern.
Das Schöne an diesem Ansatz ist, dass Sie ihn auch in Storyboards verwenden können, indem Sie ein benutzerdefiniertes Laufzeitattribut hinzufügen. Leider
UIEdgeInsets
ist es dort nicht direkt als Typ verfügbar, aber da esCGRect
auch aus einer Struktur mit vier bestehtCGFloat
, funktioniert es einwandfrei, indem Sie "Rect" auswählen und die folgenden Werte eingeben :{{top, left}, {bottom, right}}
.quelle
Ich verwende die folgende Klasse in Swift, um auch eine Interface Builder-Eigenschaft zum Anpassen des Randes zu aktivieren:
quelle
Nun, Sie können Ihren UIButton in einem transparenten und etwas größeren UIView platzieren und dann die Berührungsereignisse auf der UIView-Instanz wie im UIButton abfangen. Auf diese Weise haben Sie immer noch Ihre Schaltfläche, jedoch mit einem größeren Berührungsbereich. Sie müssen manuell mit ausgewählten und hervorgehobenen Zuständen auf der Schaltfläche umgehen, wenn der Benutzer die Ansicht anstelle der Schaltfläche berührt.
Eine andere Möglichkeit besteht darin, ein UIImage anstelle eines UIButton zu verwenden.
quelle
Ich konnte den Trefferbereich der Info-Schaltfläche programmgesteuert vergrößern. Die "i" -Grafik ändert den Maßstab nicht und bleibt im neuen Schaltflächenrahmen zentriert.
Die Größe der Info-Schaltfläche scheint im Interface Builder auf 18x19 [*] festgelegt zu sein. Durch die Verbindung mit einem IBOutlet konnte ich die Frame-Größe im Code ohne Probleme ändern.
[*]: Spätere Versionen von iOS scheinen den Trefferbereich der Info-Schaltfläche vergrößert zu haben.
quelle
Dies ist meine Swift 3- Lösung (basierend auf diesem Blogpost: http://bdunagan.com/2010/03/01/iphone-tip-larger-hit-area-for-uibutton/ )
quelle
Chases benutzerdefinierter Treffer-Test wurde als Unterklasse von UIButton implementiert. Geschrieben in Objective-C.
Es scheint sowohl für
init
als auch fürbuttonWithType:
Konstrukteure zu funktionieren . Für meine Bedürfnisse ist es perfekt, aber da UnterklassenUIButton
haarig sein können, würde mich interessieren, ob jemand einen Fehler daran hat.CustomeHitAreaButton.h
CustomHitAreaButton.m
quelle
Implementierung durch Überschreiben des geerbten UIButton.
Swift 2.2 :
quelle
WJBackgroundInsetButton.h
WJBackgroundInsetButton.m
quelle
Überschreiben Sie niemals die Methode in der Kategorie. Unterklassenschaltfläche und Überschreiben
- pointInside:withEvent:
. Verwenden Sie beispielsweise Folgendes, wenn die Seite Ihrer Schaltfläche kleiner als 44 Pixel ist (was als Mindestabgriffsfläche empfohlen wird):quelle
Zu diesem Zweck habe ich eine Bibliothek erstellt .
Sie können eine
UIView
Kategorie verwenden, ohne dass eine Unterklasse erforderlich ist :Oder Sie können Ihre UIView oder UIButton in Unterklassen unterteilen und das
minimumHitTestWidth
und / oder festlegenminimumHitTestHeight
. Ihr Button-Hit-Test-Bereich wird dann durch diese 2 Werte dargestellt.Genau wie bei anderen Lösungen wird die
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
Methode verwendet. Die Methode wird aufgerufen, wenn iOS Treffer-Tests durchführt. Dieser Blog-Beitrag enthält eine gute Beschreibung der Funktionsweise von iOS-Hit-Tests.https://github.com/kgaidis/KGHitTestingViews
Sie können den Interface Builder auch einfach unterordnen und verwenden, ohne Code zu schreiben:
quelle
Basierend auf der obigen Antwort von giaset (für die ich die eleganteste Lösung gefunden habe), hier ist die schnelle 3-Version:
quelle
So einfach ist das:
Das ist das Ganze.
quelle
Ich verwende diesen Trick für die Schaltfläche in tableviewcell.accessoryView, um den Berührungsbereich zu vergrößern
quelle
Ich habe gerade den Port der @ Chase- Lösung in Swift 2.2 erstellt
und Sie können so verwenden
Weitere Informationen finden Sie unter https://stackoverflow.com/a/13067285/1728552
quelle
@ antoines Antwort für Swift 4 formatiert
quelle
Ich habe Chases Antwort verfolgt und es funktioniert hervorragend. Ein einziges Problem, wenn Sie den Bereich zu groß erstellen, der größer als die Zone ist, in der die Schaltfläche abgewählt wird (wenn die Zone nicht größer ist), wird der Selektor für das UIControlEventTouchUpInside-Ereignis nicht aufgerufen .
Ich denke, die Größe ist über 200 in jede Richtung oder so ähnlich.
quelle
Ich bin so spät zu diesem Spiel, wollte aber eine einfache Technik abwägen, die Ihre Probleme lösen könnte. Hier ist ein typisches programmatisches UIButton-Snippet für mich:
Ich lade ein transparentes PNG-Bild für meine Schaltfläche und stelle das Hintergrundbild ein. Ich stelle den Rahmen basierend auf dem UIImage ein und skaliere für die Netzhaut um 50%. OK, vielleicht stimmen Sie dem oben Gesagten zu oder nicht, ABER wenn Sie den Trefferbereich GRÖSSER machen und sich Kopfschmerzen ersparen möchten:
Was ich mache, öffne das Bild in Photoshop und erhöhe einfach die Leinwandgröße auf 120% und speichere. Tatsächlich haben Sie gerade das Bild mit transparenten Pixeln vergrößert.
Nur ein Ansatz.
quelle
Die obige Antwort von @jlajlar schien gut und unkompliziert zu sein, stimmt jedoch nicht mit Xamarin.iOS überein, daher habe ich sie in Xamarin konvertiert. Wenn Sie nach einer Lösung für ein Xamarin iOS suchen, finden Sie hier:
Sie können diese Methode der Klasse hinzufügen, in der Sie UIView oder UIImageView überschreiben. Das hat gut funktioniert :)
quelle
Keine der Antworten funktioniert perfekt für mich, da ich ein Hintergrundbild und einen Titel auf dieser Schaltfläche verwende. Darüber hinaus wird die Größe der Schaltfläche geändert, wenn sich die Bildschirmgröße ändert.
Stattdessen vergrößere ich den Tap-Bereich, indem ich den transparenten PNG-Bereich vergrößere.
quelle