jak mogę wykryć zdarzenie dotykowe UIImageView


97

Umieściłem obraz (UIImageView) na pasku nawigacyjnym. Teraz chcę wykryć zdarzenie dotyku i obsłużyć zdarzenie. Czy możesz dać mi znać, jak mam to zrobić?

Dzięki.


W tej sytuacji użyłbym (i myślę, że powinieneś) zamiast tego użyć niestandardowego UIButton.
titaniumdecoy

Odpowiedzi:


137

W praktyce nie rób tego.

Zamiast tego dodaj przycisk ze stylem niestandardowym (bez grafiki przycisku, chyba że określisz obrazy) w UIImageView. Następnie dołącz dowolne metody, które chcesz do tego wywołać.

Możesz użyć tej techniki w wielu przypadkach, w których naprawdę chcesz, aby jakiś obszar ekranu działał jak przycisk, zamiast bawić się dotykiem.


Dodałem przycisk na pasku nawigacyjnym i mogę również obsługiwać zdarzenia dotykowe. Jednak chcę dodać okrągły obraz na tym przycisku. Czy możesz mi powiedzieć, jak mogę to zrobić programowo? Czy możesz również dać mi znać, jak programowo ustawić właściwość przycisku na „niestandardową”?
ebaccount

Spójrz na dokumentację dla UIButton - musisz ustawić obrazy tła dla stanu kontrolnego, będziesz potrzebować różnych obrazów dla Normalny i Wybrany / Podświetlony. Wydaje mi się, że styl przycisku jest taki, jaki ustawiłeś na UIButtonStyleCustom - ponownie spójrz na dokumentację dotyczącą właściwości style w UIButton.
Kendall Helmstetter Gelner

1
Czy dodanie UIButton na górze UIImageView nie jest trochę przesadzone? Dodajesz dodatkowy obiekt, podczas gdy możesz po prostu zaimplementować metody dotknięć już istniejącego obiektu UIImageView. Nie?
samvermette

32
Jeśli spojrzysz na rozmiar UIButton w pamięci, to praktycznie nic i masz tylko kilka na ekran. To, co dostajesz za darmo, to całe okablowanie akcji celu dla różnych stanów (takich jak dotyk w środku), a także przyjemne zachowanie, takie jak brak wyzwalania po naciśnięciu, ale przesunięcie palcem w bok. Zasadniczo przyciski są jednym z najlepiej wykonanych obiektów w całym systemie i myślenie, że zamierzasz wykonać niestandardowy kod dotykowy, który działa lepiej, jest szaleństwem. Użyj tego, co jest tanie i działa dobrze, zachowaj niestandardową pracę dla rzeczy, których frameworki jeszcze nie obsługują.
Kendall Helmstetter Gelner

6
Możesz również nałożyć UIControl, jeśli wszystko, czego potrzebujesz, to zdarzenia dotykowe (przez addTaget: action: forControlEvents :). To trochę tańsze niż UIButton, który ma obrazy i kilka stanów. Ponadto używam warunków warunkowych preprocesora, aby zmienić kolor tła nałożonej kontrolki na różowy, dzięki czemu mogę dokładnie zobaczyć, gdzie się znajdują (i pamiętać, że istnieją :-).
Jeff

115

A UIImageViewwywodzi się z a UIViewktóry pochodzi z, UIResponderwięc jest gotowy do obsługi zdarzeń dotykowych. Będziemy chcieli, aby zapewnić touchesBegan, touchesMovedoraz touchesEndedmetody i skąd będą wywoływane, gdy użytkownik kliknie obraz. Jeśli chcesz tylko zdarzenia dotknięcia, łatwiej jest po prostu użyć niestandardowego przycisku z obrazem ustawionym jako obraz przycisku. Ale jeśli chcesz mieć dokładniejszą kontrolę nad stuknięciami, ruchami itp., To jest droga.

Będziesz także chciał przyjrzeć się kilku innym rzeczom:

  • Zastąp canBecomeFirstResponderi zwróć TAK, aby wskazać, że widok może stać się punktem skupienia zdarzeń dotykowych (domyślnie NIE).

  • Ustaw userInteractionEnabledwłaściwość na TAK. Wartość domyślna dla UIViewsto TAK, ale dla UIImageViewsjest NIE, więc należy ją wyraźnie włączyć.

  • Jeśli chcesz reagować na zdarzenia wielodotykowe (np. Szczypanie, powiększanie itp.), Wybierz ustawienie multipleTouchEnabledTAK.


Próbowałem tego, ale mimo wszystko nie dostaję dotyku Rozpoczęte wydarzenia ... dlaczego tak jest?
Markus

5
@Markus: Miałem ten sam problem, ale naprawiłem go, ustawiając userInteractionEnabledTAK w widoku rodzica. Zobacz stackoverflow.com/questions/5887305/…
Saxon Druce

51

Aby dodać zdarzenie dotyku do UIImageView, użyj następujących elementów w pliku .m

UITapGestureRecognizer *newTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(myTapMethod)];

[myImageView setUserInteractionEnabled:YES];

[myImageView addGestureRecognizer:newTap];


-(void)myTapMethod{
    // treat image tap
}

mam nadzieję, że to pomoże.


userInteractionEnabled = true to część, o której łatwo zapomnieć, dzięki.
Michael Peterson

23

Możesz również dodać UIGestureRecognizer. Nie wymaga dodawania dodatkowego elementu w hierarchii widoków, ale nadal zapewnia cały ładnie napisany kod do obsługi zdarzeń dotykowych z dość prostym interfejsem:

    UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc]
                                            initWithTarget:self action:@selector(handleSwipe:)];
    swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
    [imgView_ addGestureRecognizer:swipeRight];        
    [swipeRight release];
    UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc]
                                            initWithTarget:self action:@selector(handleSwipe:)];
    swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
    [imgView_ addGestureRecognizer:swipeLeft];
    [swipeLeft release];

10
NIE zapomnij ustawić UserInteractionEnabled dla imgView_
Anonymous White

13

W ciągu ostatnich kilku godzin byłem w różnych wątkach, próbując znaleźć rozwiązanie mojego problemu, ale bezskutecznie. Widzę, że wielu deweloperów podziela ten problem i myślę, że ludzie tutaj o tym wiedzą. Mam wiele obrazów w środku UIScrollView, próbując uzyskać na nich zdarzenia dotknięcia.

nie otrzymuję żadnych zdarzeń z obiektu UIImangeView, ale otrzymuję zdarzenie z podobnego UILablez bardzo podobnymi parametrami, które ustawiam. pod IOS 5.1.

Wykonałem już następujące czynności:

  1. ustaw setUserInteractionEnabled na YES zarówno dla `UIImageView, jak i widoku nadrzędnego.
  2. ustaw setMultipleTouchEnabled na YES dla UIImageView.
  3. Próbowałem podklasy UIImageView, nic nie pomogło.

Załączam kod poniżej, w tym kodzie inicjalizuję zarówno UIImageViewa UILabel, jak i , etykieta działa dobrze pod względem zdarzeń odpalania. Próbowałem unikać nieistotnego kodu. Dzięki chłopaki, Ilan

UIImageView *single_view = [[UIImageView alloc]initWithFrame:CGRectMake(200, 200, 100, 100)];
single_view.image=img;
single_view.layer.zPosition=4;

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureCaptured:)];
[single_view addGestureRecognizer:singleTap];
[single_view setMultipleTouchEnabled:YES];
[single_view setUserInteractionEnabled:YES];
[self.myScrollView addSubview:single_view];    
self.myScrollView.userInteractionEnabled=YES;

UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
testLabel.backgroundColor=[UIColor redColor];
[self.myScrollView addSubview:testLabel];
[testLabel addGestureRecognizer:singleTap];  
[testLabel setMultipleTouchEnabled:YES];
[testLabel setUserInteractionEnabled:YES];
testLabel.layer.zPosition=4;

Oraz metoda obsługująca zdarzenie:

- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{ 
    UIView *tappedView = [gesture.view hitTest:[gesture locationInView:gesture.view] withEvent:nil];
    NSLog(@"Touch event on view: %@",[tappedView class]);
}

Jak powiedziano, odebrano dotknięcie etykiety.


6

Zamiast tworzyć dotykalny widok UIImageView, a następnie umieszczać go na pasku nawigacyjnym, należy po prostu utworzyć UIBarButtonItem, który tworzy się z UIImageView.

Najpierw utwórz widok obrazu:

UIImageView *yourImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"nameOfYourImage.png"]];

Następnie usuń element z kolcem z widoku obrazu:

UIBarButtonItem *yourBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:yourImageView];

Następnie dodaj przycisk paska do paska nawigacji:

self.navigationItem.rightBarButtonItem = yourBarButtonItem;

Pamiętaj, że ten kod trafia do kontrolera widoku, który znajduje się w tablicy kontrolera widoku kontrolera nawigacji. Zasadniczo więc ten „dotykowy przycisk paska przypominający obraz” pojawi się na pasku nawigacji tylko wtedy, gdy ten kontroler widoku jest wyświetlany. Po naciśnięciu innego kontrolera widoku ten przycisk paska nawigacji zniknie ~


3

To, co możesz chcieć zrobić, to przesłonić touchesBegan:withEvent:metodę UIView(lub podklasy), która zawiera Twój UIImageViewwidok podrzędny.

W ramach tej metody sprawdź, czy którykolwiek z UITouchdotknięć znajduje się w granicach UIImageViewinstancji (powiedzmy, że jest wywoływany imageView).

To znaczy, czy CGPointelement [touch locationInView]przecina się z CGRectelementem [imageView bounds]? Zajrzyj do funkcji, CGRectContainsPointaby uruchomić ten test.


Dzięki za odpowiedź. Dodałem taki widok: [navBar addSubview: self.pImage]; // dodany jako widok podrzędny paska nawigacji. Funkcja została zastąpiona, ale funkcja nigdy nie jest wywoływana. Ustawiłem jednak właściwość userInteractionEnabled UIImageView na YES. Czy coś mi brakuje?
ebaccount

Sprawdź akcentyBegan: withEvent: method. W wyszukiwarkach jest wiele przykładów tego, jak to działa.
Alex Reynolds

1

Najpierw umieść przycisk UIButton, a następnie albo możesz dodać obraz tła dla tego przycisku, albo musisz umieścić UIImageView nad przyciskiem.

lub

Możesz dodać gest stuknięcia do UIImageView, aby uzyskać akcję kliknięcia po dotknięciu UIImageView.


0

Dla tych z Was, którzy szukają rozwiązania Swift 4 na tę odpowiedź. Możesz użyć następujących, aby wykryć zdarzenie dotyku w UIImageView.

let gestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageViewTapped))
imageView.addGestureRecognizer(gestureRecognizer)
imageView.isUserInteractionEnabled = true

Następnie musisz zdefiniować swój selektor w następujący sposób:

@objc func imageViewTapped() {
    // Image has been tapped
}

-2

Dodaj gest do tego widoku. Dodaj obraz do tego widoku, a następnie wykryje gest również na obrazie. Czy możesz spróbować z metodą delegata zdarzenia dotykowego, a następnie w takim przypadku może to również wykrywać. Dzięki

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.