2010-08-24 13 views
7

Jestem całkiem nowy w tworzeniu aplikacji dla systemu Android, a ja bawię się gestami machnięcia przy użyciu SimpleOnGestureListener Androida i ViewFlipper. Istnieją 3 dzieci w ViewFlipper, a każdy z nich to ScrollView. Wszystkie są dynamicznie zapełniane po załadowaniu działania i nie zmieniają się po tym. ScrollView jest tam, gdzie dołączone są SimpleOnGestureListeners.Scrollview nie przesuwa palcem, gdy jest za krótki, aby przewinąć

Oto układ Używam:
+ ViewFlipper
++ Scrollview (x3, po jednym dla każdej ze stron, każda z następujących :)
+++ LinearLayout (w pionie)
++++ TextView
++++ TableLayout (dynamicznie wypełniane w/TableRows)
++++ Zobacz

i rozszerzone metody onFling ze wspólnym kodem samouczka można znaleźć nigdzie w internecie, i działa świetnie - z wyjątkiem gdy jeden z ScrollViews nie zawiera wystarczającej ilości treści do przewinięcia l.

Zmniejszyłem problem, wykrywając dotyk poprzez nadpisanie i wywołanie super na każdej z metod SimpleOnGestureListener w celu dodania dziennika do dziennika.

Po przesunięciu strony, która przewija się, otrzymuję coś pełnego "inClick" "w onScroll" "w onFling" itp. Na stronie, która jest zbyt krótka, aby przewijać, pojawia się "inClick" "w onShowPress "" w onLongPress ", i to tylko wtedy, gdy dotykam treści w ciągu dzieci zbyt krótkiego przewijania - jeśli dotknę ich gdzie indziej, nie otrzymam żadnych zdarzeń.

Pomysły na temat tego, co jest nie tak, lub jak wykryć gest machnięcia, bez względu na to, jak duży jest ScrollView?

EDYCJA: Stwierdziłem, że po uruchomieniu tego na emulatorze Androida 2.2, w przeciwieństwie do emulatora DroidX Android 2.1u1, którego używałem, znika. Jest to powtarzalne w wielu środowiskach.


Mam więcej wglądu na to; wydaje się, że onInterceptTouchEvent nie jest wywoływany dla każdego zdarzenia ruchu, gdy przewijany widok znajduje się w flipper (lub WorkspaceView).

W szczególności zachowanie znalazłem podczas modyfikowania innej klasy widoku, aby rozwiązać ten sam problem bardzo (nie jest przypisany do płetwy) była następująca - zauważ, że jest to tylko Android 2.1:

Jeśli Scrollview jest wystarczająco długi, aby przewinąć, zdarzenie ruchu ACTION_DOWN jest przechwytywane przez ScrollView, a każde kolejne zdarzenie ACTION_MOVE przechodzi przez onInterceptTouchEvent z flippera, gdzie jest odpowiednio przechwytywane i obsługiwane. W systemie Android 2.2 to zachowanie dzieje się niezależnie od długości przewijania.

Powrót do 2.1: Jeśli przewijanie nie jest wystarczająco długie, aby przewinąć, zdarzenie ruchu ACTION_DOWN jest nie przechwycone przez scrollview, ale wraca do onTouchEvent z flippera. Wszystkie kolejne zdarzenia ACTION_MOVE tego samego gestu: pomiń funkcję onInterceptTouchEvent i przejdź bezpośrednio do funkcji onTouchEvent!

Sposób, w jaki to rozwiązałem, polegał na przejmowaniu funkcji, którą miałem w zdarzeniu onTouchEvent dla zdarzeń ACTION_MOVE i przekształceniu go we własną metodę. W ten sposób mogę mieć wywołanie onTouchEvent onInterceptTouchEvent, po którym następuje ta funkcja, jeśli wykryje, że zdarzenie zostało wcześniej nieobsługiwane.

case MotionEvent.ACTION_MOVE: 

       if (touchState == TOUCH_STATE_SCROLLING) { 
        handleScrollMove(ev); 
       } else { 
    //    Log.d("workspace","caught a move touch event but not scrolling"); 
        //NOTE: We will never hit this case in Android 2.2. This is to fix a 2.1 bug. 
        //We need to do the work of interceptTouchEvent here because we don't intercept the move 
        //on children who don't scroll. 

        Log.d("workspace","handling move from onTouch"); 

        if(onInterceptTouchEvent(ev) && touchState == TOUCH_STATE_SCROLLING){ 
         handleScrollMove(ev); 
        } 

       } 

       break; 

To z WorkspaceView.java (modyfikacja Androida Workspace.java, na stronie projektu andro-poglądy na Google Code, a teraz tutaj: Horizontal "tab"ish scroll between views). W przypadku, gdy otrzymamy zdarzenie przeniesienia i przewijamy (co dzieje się tylko wtedy, gdy świadomie zdecydowaliśmy się go przechwycić - tj. Jest ustawione w funkcji przechwytywania, więc byliśmy już w funkcji przechwytywania) wykonujemy zachowanie, którego pragniemy. Jeśli otrzymamy tutaj zdarzenie przeniesienia i nie będziemy przewijali, to wysyłamy zdarzenie z powrotem przez OnIntercept, a następnie sprawdzamy, czy mamy teraz przewijanie. Jeśli tak, wykonujemy akcję.

To nie jest eleganckie, ale działa!

Odpowiedz

7

Musiałem stworzyć nową klasę, która przedłużony Scrollview i wykorzystywane to:.

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    super.onTouchEvent(event); 
    return gestureDetector.onTouchEvent(event); 
} 

@Override 
public boolean dispatchTouchEvent(MotionEvent ev){ 
    gestureDetector.onTouchEvent(ev); 
    super.dispatchTouchEvent(ev); 
    return true; 
} 

nie mam pojęcia dlaczego, ale jeśli starają się powrócić bynajmniej prawdą w dispatchTouchEvent (logiczną rzeczą byłoby

return (gestureDetector.onTouchEvent(ev) || super.dispatchTouchEvent(ev)); 

jeśli rozumiem poprawnie), to nie działa, a to robi.

1

Spróbuj ustawić android:fillViewport="true" w układzie xml dla każdego z ScrollView s. Że opowiada ScrollView być tak duża jak widzenia zawartej w

+0

Jest ustawiany jako taki dla wszystkich dzieci. Nawet bezpośrednio skopiowałem i wkleiłem kod XML na http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+PlanetAndroidCom+(Planet+Android) i próbowałem go jako widok podrzędny. Po kilku manipulacjach udało mi się je wszystkie wypełnić okienkiem. Ale bez powodzenia na callbacku, nawet gdy już to zrobili. Jak dotąd nie ma paska przewijania = nie onFling. –

Powiązane problemy