Mam pytanie dotyczące UIButton i jego obszaru działania. Używam przycisku Info Dark w kreatorze interfejsów, ale odkrywam, że obszar trafienia nie jest wystarczająco duży dla palców niektórych osób.
Czy istnieje sposób na zwiększenie obszaru działania przycisku albo programowo, albo w Konstruktorze interfejsów bez zmiany rozmiaru grafiki InfoButton?
ios
cocoa-touch
uibutton
uikit
Kevin Bomberry
źródło
źródło
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return bounds.insetBy(dx: -20, dy: -20).contains(point) }
Odpowiedzi:
Ponieważ używam obrazu tła, żadne z tych rozwiązań nie działało dla mnie dobrze. Oto rozwiązanie, które zapewnia zabawną magię typu „cel-c” i oferuje rozwiązanie z minimalnym kodem.
Najpierw dodaj kategorię,
UIButton
która zastępuje test trafienia, a także dodaje właściwość do rozszerzenia ramki testu trafienia.UIButton + Extensions.h
UIButton + Extensions.m
Po dodaniu tej klasy wszystko, co musisz zrobić, to ustawić wypustki krawędzi przycisku. Zauważ, że zdecydowałem się dodać wypustki, więc jeśli chcesz powiększyć obszar trafienia, musisz użyć liczb ujemnych.
Uwaga: Pamiętaj o zaimportowaniu kategorii (
#import "UIButton+Extensions.h"
) do swoich klas.źródło
[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"arrow.png"] forState:UIControlStateNormal];
Po prostu ustaw szerokość i wysokość, których potrzebujesz: `backButton.frame = CGRectMake (5, 28, 45, 30);`Wystarczy ustawić wartości wstawek krawędzi obrazu w narzędziu do tworzenia interfejsów.
źródło
button.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10);
Oto eleganckie rozwiązanie wykorzystujące rozszerzenia w Swift. Daje wszystkim przyciskom UIB obszar trafienia wynoszący co najmniej 44 x 44 punkty, zgodnie z wytycznymi Apple Interface Human ( https://developer.apple.com/ios/human-interface-guidelines/visual-design/layout/ )
Swift 2:
Swift 3:
źródło
Możesz również
UIButton
utworzyć podklasę lub niestandardoweUIView
i zastąpić je zapoint(inside:with:)
pomocą:Szybki 3
Cel C
źródło
Oto rozszerzenia UIButton + Chase w Swift 3.0.
Aby z niego skorzystać, możesz:
źródło
UIControl
, nieUIButton
.pTouchAreaEdgeInsets
musi byćInt
, nieUIEdgeInsets
. (Właściwie może to być dowolny typ, aleInt
jest to najbardziej ogólny i najprostszy typ, więc jest powszechny w takiej konstrukcji). (Dlatego ogólnie podoba mi się to podejście. Dziękuję, dcRay!)Zalecam umieszczenie przycisku UIB z typem Niestandardowym wyśrodkowanym nad przyciskiem informacyjnym. Zmień rozmiar przycisku niestandardowego do rozmiaru, w którym ma znajdować się obszar działania. Stamtąd masz dwie opcje:
Zaznacz opcję „Pokaż dotyk po podświetleniu” przycisku niestandardowego. Biała poświata pojawi się nad przyciskiem informacyjnym, ale w większości przypadków palec użytkownika to zakryje i wszystko, co zobaczą, to poświata na zewnątrz.
Skonfiguruj IBOutlet dla przycisku informacyjnego i dwie IBAction dla przycisku niestandardowego, jeden dla „Touch Down” i jeden dla „Touch Up Inside”. Następnie w Xcode ustaw zdarzenie przyziemienia ustaw podświetloną właściwość przycisku informacyjnego na TAK, a zdarzenie touchupinside ustaw wyróżnioną właściwość na NIE.
źródło
Nie ustawiaj
backgroundImage
właściwości za pomocą obrazu, ustawimageView
właściwość. Upewnij się również, żeimageView.contentMode
ustawiłeś naUIViewContentModeCenter
.źródło
imageView.contentMode
Można ustawićUIContentModeCenter
.[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
Moje rozwiązanie w Swift 3:
źródło
Nie ma nic złego w przedstawionych odpowiedziach; chciałem jednak rozszerzyć odpowiedź jlarjlar, ponieważ ma niesamowity potencjał, który może wnieść wartość do tego samego problemu z innymi kontrolkami (np. SearchBar). Wynika to z faktu, że ponieważ pointInside jest dołączony do UIView, można podklasować dowolną kontrolę, aby poprawić obszar dotyku. Ta odpowiedź pokazuje również pełną próbę wdrożenia pełnego rozwiązania.
Utwórz nową podklasę dla swojego przycisku (lub dowolnej kontrolki)
Następnie zastąp metodę pointInside w implementacji podklasy
W pliku storyboard / xib wybierz kontrolkę, o której mowa, otwórz inspektora tożsamości i wpisz nazwę swojej klasy niestandardowej.
W klasie UIViewController dla sceny zawierającej przycisk zmień typ klasy przycisku na nazwę swojej podklasy.
Połącz przycisk scenorysu / xib z właściwością IBOutlet, a obszar dotykowy zostanie rozszerzony, aby pasował do obszaru zdefiniowanego w podklasie.
Oprócz zastąpienia metody pointInside razem z metodami CGRectInset i CGRectContainsPoint , należy poświęcić trochę czasu na zbadanie CGGeometry w celu rozszerzenia prostokątnego obszaru dotykowego dowolnej podklasy UIView. W NSHipster możesz także znaleźć kilka dobrych wskazówek na temat przypadków użycia CGGeometry .
Na przykład można sprawić, że obszar dotyku jest nieregularny, stosując metody wymienione powyżej, lub po prostu wybrać, aby szerokość obszaru dotyku była dwa razy większa niż pozioma powierzchnia dotyku:
NB: Zastąpienie dowolnego elementu sterującego klasy interfejsu użytkownika powinno dać podobne wyniki przy rozszerzaniu obszaru dotykowego dla różnych elementów sterujących (lub dowolnej podklasy UIView, takiej jak UIImageView itp.).
źródło
To działa dla mnie:
źródło
Nie zmieniaj zachowania UIButton.
źródło
Używam bardziej ogólnego podejścia poprzez zamiatanie
-[UIView pointInside:withEvent:]
. To pozwala mi modyfikować działanie testowania trafień na dowolnymUIView
, nie tylkoUIButton
.Często w widoku kontenera umieszczany jest przycisk, który również ogranicza testowanie trafienia. Na przykład, gdy przycisk znajduje się u góry widoku kontenera i chcesz rozszerzyć cel dotykowy w górę, musisz także rozszerzyć cel dotykowy w widoku kontenera.
Zaletą tego podejścia jest to, że można go używać nawet w Storyboardach, dodając zdefiniowany przez użytkownika atrybut środowiska wykonawczego. Niestety,
UIEdgeInsets
nie jest bezpośrednio dostępny jako typ tam, ale ponieważCGRect
składa się także z czterech structCGFloat
działa bezbłędnie, wybierając „Rect” i wypełnienie w wartościach takich jak ten:{{top, left}, {bottom, right}}
.źródło
Używam następującej klasy w Swift, aby również włączyć właściwość Konstruktora interfejsów, aby dostosować margines:
źródło
Cóż, możesz umieścić swój UIButton w przezroczystym i nieco większym UIView, a następnie przechwytywać zdarzenia dotyku w instancji UIView jak w UIButton. W ten sposób nadal będziesz mieć swój przycisk, ale z większym obszarem dotykowym. Będziesz musiał ręcznie poradzić sobie z wybranymi i wyróżnionymi stanami za pomocą przycisku, jeśli użytkownik dotknie widoku zamiast przycisku.
Inna możliwość obejmuje użycie UIImage zamiast UIButton.
źródło
Udało mi się programowo zwiększyć obszar działania przycisku informacyjnego. Grafika „i” nie zmienia skali i pozostaje wyśrodkowana w nowej ramce przycisku.
Rozmiar przycisku informacyjnego wydaje się być ustalony na 18x19 [*] w Konstruktorze interfejsów. Podłączając go do IBOutleta, bez żadnych problemów mogłem zmienić rozmiar ramki w kodzie.
[*]: Późniejsze wersje iOS wydają się zwiększać obszar działania przycisku informacyjnego.
źródło
To jest moje rozwiązanie Swift 3 (oparte na tym blogu: http://bdunagan.com/2010/03/01/iphone-tip-larger-hit-area-for-uibutton/ )
źródło
Niestandardowy test trafień Chase'a zaimplementowany jako podklasa UIButton. Napisane w Objective-C.
Wydaje się działać zarówno dla konstruktorów, jak
init
i dla nichbuttonWithType:
. Na moje potrzeby jest idealny, ale ponieważ podklasyUIButton
mogą być owłosione, chciałbym wiedzieć, czy ktoś ma z tym winę.CustomeHitAreaButton.h
CustomHitAreaButton.m
źródło
Implementacja poprzez zastąpienie odziedziczył UIButton.
Swift 2.2 :
źródło
WJBackgroundInsetButton.h
WJBackgroundInsetButton.m
źródło
Nigdy nie zastępuj metody w kategorii. Przycisk i zastąpienie podklasy
- pointInside:withEvent:
. Na przykład, jeśli strona przycisku jest mniejsza niż 44 piksele (co jest zalecane jako minimalna powierzchnia do zerwania), użyj tego:źródło
W tym celu stworzyłem bibliotekę .
Możesz wybrać użycie
UIView
kategorii, nie jest wymagana podklasa :Lub możesz podklasować UIView lub UIButton i ustawić
minimumHitTestWidth
i / lubminimumHitTestHeight
. Obszar testu trafień przycisku będzie wówczas reprezentowany przez te 2 wartości.Podobnie jak inne rozwiązania, wykorzystuje tę
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
metodę. Metoda jest wywoływana, gdy iOS wykonuje test trafień. Ten post na blogu zawiera dobry opis działania testowania trafień w systemie iOS.https://github.com/kgaidis/KGHitTestingViews
Możesz także po prostu podklasować i używać Konstruktora interfejsów bez pisania kodu:
źródło
Opierając się na powyższej odpowiedzi Giaset (która znalazłem najbardziej eleganckie rozwiązanie), oto wersja szybka 3:
źródło
To takie proste:
To wszystko.
źródło
Używam tej sztuczki do przycisku wewnątrz tableviewcell.accessoryView, aby powiększyć obszar dotykowy
źródło
Właśnie zrobiłem port rozwiązania @Chase w swift 2.2
możesz użyć w ten sposób
Wszelkie inne odniesienia można znaleźć na stronie https://stackoverflow.com/a/13067285/1728552
źródło
Odpowiedź @ antoine sformatowana dla Swift 4
źródło
Śledziłem odpowiedź Chase'a i działa świetnie, jeden pojedynczy problem, gdy tworzysz obszar zbyt duży, większy niż strefa, w której przycisk jest wyłączany (jeśli strefa nie jest większa), nie wywołuje selektora dla zdarzenia UIControlEventTouchUpInside .
Myślę, że rozmiar przekracza 200 w dowolnym kierunku lub coś w tym rodzaju.
źródło
Jestem spóźniony do tej gry, ale chciałem rozważyć prostą technikę, która może rozwiązać twoje problemy. Oto typowy dla mnie programowy fragment kodu UIButton:
Ładuję przezroczysty obraz png dla mojego przycisku i ustawiam obraz tła. Ustawiam ramkę na podstawie obrazu UII i skalowanie o 50% dla siatkówki. OK, może zgadzasz się z powyższym lub nie, ALE jeśli chcesz, aby obszar trafienia był WIĘKSZY i zaoszczędzić sobie bólu głowy:
Co robię, otwórz obraz w Photoshopie i po prostu zwiększ rozmiar płótna do 120% i zapisz. Skutecznie właśnie powiększyłeś obraz przezroczystymi pikselami.
Tylko jedno podejście.
źródło
Powyższa odpowiedź @jlajlar wydawała się dobra i prosta, ale nie pasuje do Xamarin.iOS, więc przekonwertowałem ją na Xamarin. Jeśli szukasz rozwiązania na Xamarin iOS, oto on:
Możesz dodać tę metodę do klasy, w której zastępujesz UIView lub UIImageView. To działało ładnie :)
źródło
Żadna z odpowiedzi nie jest dla mnie idealna, ponieważ używam obrazu tła i tytułu na tym przycisku. Ponadto rozmiar przycisku zmieni się wraz ze zmianą rozmiaru ekranu.
Zamiast tego powiększam obszar zaczepu, zwiększając przezroczysty obszar png.
źródło