2011-01-07 10 views
35

Dzisiaj w czasie mojej twórczości przeprowadziłem dość kompleksowe badania, jak ukraść elementy dotykowe z UIScrollView i natychmiast wysłać je do określonego podglądu, zachowując domyślne zachowanie dla pozostałej części widoku przewijania. Rozważ umieszczenie UIPickerView wewnątrz UITableView. Domyślne zachowanie polega na tym, że jeśli przeciągniesz palcem po widoku selektora, widok przewijania zostanie przewinięty, a widok wyboru pozostanie niezmieniony.Jak ukraść dotknięcia z UIScrollView?

Pierwszą rzeczą próbowałem było zastąpić

- (BOOL)touchesShouldCancelInContentView:(UIView *)view 

i po prostu nie pozwalają UIScrollView aby anulować akcenty wewnątrz widoku kompletowania. Działa to, ale ma nieprzyjemny efekt uboczny. Chciałbyś, aby widok picker odpowiedział natychmiast, a zatem będziesz musiał ustawić delaysContentTouches na NIE. Problem polega na tym, że nie chcesz, aby reszta widoku tabeli natychmiast reagowała, ponieważ w przeciwnym wypadku komórka widoku tabeli będzie zawsze podświetlana przez kilka milisekund zanim rozpocznie się przewijanie.

Drugą rzeczą próbowałem było zastąpić

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 

bo czytałem, że widok przewijania zawsze zwraca się, więc, że będzie to „kradzież” akcenty z jego subviews a później przesłać je do podrzędny jeśli nie były interesujące dla widoku przewijania. Jednak nie jest to już prawdą. Domyślna implementacja parametru hitTest w aplikacji UIScrollView: withEvent: w rzeczywistości zwraca podgląd, który powinien zostać dotknięty. Zamiast tego używa identyfikatorów do przechwytywania dotknięć.

Trzecią rzeczą, którą próbowałem, było zaimplementowanie własnego aparatu rozpoznawania gestów i spowodowanie niepowodzenia, jeśli dotknięcie wykracza poza widok próbny i inaczej się uda. Potem ustawić wszystkie gest rozpoznawania, czyli recognizers widoku zwoju na niepowodzenie, chyba mój gest rozpoznawania powiodło się za pomocą następującego kodu:

for (UIGestureRecognizer * gestureRecognizer in self.tableView.gestureRecognizers) 
{ 
    [gestureRecognizer requireGestureRecognizerToFail:myRecognizer]; 
} 

ten ma w rzeczywistości ukraść akcenty z widoku przewijania, ale widok kompletacji ich nie odbiera. Więc chociaż może ja może po prostu wysłać wszystkie akcenty że mój gest rozpoznawania odbiera przy użyciu tego kodu:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    for (UITouch *touch in touches) 
     [touch.view touchesBegan:touches withEvent:event]; 
} 

Powyższy kod jest uproszczoną wersją. Upewniam się także, że widok jest widokiem selektora (lub jednym z jego podrzędnych widoków) i ustawi odpowiedni stan dla narzędzia do rozpoznawania gestów, o czym wspomniałem powyżej. Zrobiłem to samo dla anulowania, zakończenia i przeniesienia. Widok selektora nadal nie odpowiadał.

Próbowałem też jeszcze jednej rzeczy przed powrotem do mojej normalnej pracy. Podczas mojej rozległej googling Czytałem, że zagnieżdżone UIScrollViews prostu magicznie pracował od 3.x, więc starałem oddanie mój pogląd kompletacji wewnątrz zagnieżdżonej UIScrollView i ustaw następujące właściwości na nim:

scrollView.delaysContentTouches = NO; 
scrollView.canCancelContentTouches = NO; 

Jak można było oczekiwać zewnętrzny zwój Widok nie traktował wewnętrznego widoku przewijania inaczej niż traktował widok selektora, więc wewnętrzny widok przewijania nie otrzymał dotknięć. Myślałem, że to był długi strzał, ale było to dość łatwe do wdrożenia, więc pomyślałem, że warto było go spróbować.

Wiem, że UIScrollView ma narzędzie do rozpoznawania gestów o nazwie UIScrollViewDelayedTouchesBeganGestureRecognizer, które przechwytuje dotknięcia i wysyła je do odpowiedniego podglądu po 150 (?) Ms. Myślę, że powinienem móc napisać podobny czytnik, który powoduje, że domyślne rozpoznawanie przewijania nie działa, a zamiast opóźniania dotknięć natychmiast wysyła je do widoku próbnego.Jeśli więc ktoś wie, jak napisać taki aparat rozpoznawczy, daj mi znać, a jeśli masz inne rozwiązanie tego problemu, to bardzo proszę, podziel się nim z nami.

Dziękujemy za przeczytanie całego pytania, a nawet jeśli nie znasz odpowiedzi, możesz odpowiedzieć na pytanie, aby uzyskać więcej uwagi (miejmy nadzieję od kogoś, kto może na nie odpowiedzieć). Dzięki! :)

Odpowiedz

32

Czasami musisz zadać pytanie, zanim znajdziesz odpowiedź. Dan Ray miał podobny problem i rozwiązał go z zupełnie innym rozwiązaniem.

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    UIView* result = [super hitTest:point withEvent:event]; 

    if ([result.superview isKindOfClass:[UIPickerView class]]) 
    { 
     self.scrollEnabled = NO; 
    } 
    else 
    { 
     self.scrollEnabled = YES;  
    } 
    return result; 
} 

Testowałem kod i działa on również dobrze dla mnie. Jednak nie jest to naprawdę kradzież dotyku z widoku przewijania, więc jeśli ktoś wie, jak ukraść dotknięcia, które byłyby świetne.

Źródło: UIPickerView inside UITableView.tableFooterView doesn't receive drag touches

+0

Ponieważ nadal jest jedyną odpowiedzią, ja przyjmuję je jako moją odpowiedź, ale jeśli masz lepsze rozwiązanie, nie wahaj się go udostępnić! –

+0

To jest moje preferowane rozwiązanie. Jest szczupły i podły i po prostu działa. Wielkie dzięki! – DrMickeyLauer

+1

Doskonale, dla moich potrzeb zmieniłem go na '([wynik toKindOfClass: [klasa UITableView]] || [result.superview isKindOfClass: [klasa UITableView]] || [result.superview isKindOfClass: [klasa UITableViewCell]]) ' – Diziet

Powiązane problemy