2010-08-24 6 views
7

Ich bin ziemlich neu in der Entwicklung von Android-Apps und habe mit Swipe-Gesten mit dem SimpleOnGestureListener von Android und einem ViewFlipper herumgespielt. Es gibt 3 Kinder des ViewFlipper, und jeder ist ein ScrollView. Sie werden alle dynamisch geladen, wenn die Aktivität geladen wird, und sie ändern sich danach nicht mehr. In der ScrollView sind die SimpleOnGestureListeners angehängt.Scrollview wischt nicht, wenn es zu kurz ist, um zu scrollen

Hier ist das Layout Ich verwende:
+ ViewFlipper
++ Scroll (x3, eine für jede Seite, die jeweils mit dem folgenden :)
+++ Linearlayout (vertikal)
++++ Textview
++++ Tablelayout (dynamisch bevölkerten w/TableRows)
++++ Ansicht

verlängert ich die onFling Methode mit dem gemeinsamen Code-Tutorial Sie überall online finden können, und es funktioniert super - es sei denn, Eine der ScrollViews enthält nicht genügend Inhalte zum Scrollen l.

Ich habe das Problem auf Berührungserkennung eingegrenzt, indem ich überschreibe und super auf jeder der Methoden des SimpleOnGestureListener aufruft, um ein print-to-log hinzuzufügen.

Wenn ich auf einer Seite wische, die scrollt, bekomme ich etwas "on onClick" "in onScroll" "in onFling" usw. Auf einer Seite, die zu kurz ist, um zu scrollen, bekomme ich "in onClick" in onShowPress "" in "OnLongPress", und das ist nur, wenn ich den Inhalt innerhalb die Kinder der zu kurzen scrollview berühren - wenn ich anderswo berühre, bekomme ich überhaupt keine Ereignisse.

Ideen, was falsch ist, oder wie man die Wischgeste erkennt, egal wie groß die ScrollView ist?

EDIT: Ich habe festgestellt, dass, wenn ich dies auf einem Android 2.2-Emulator, im Gegensatz zu dem Android 2.1u1 DroidX Emulator, die ich verwendet habe, läuft es weg. Dies ist in mehreren Umgebungen reproduzierbar.


Ich habe mehr Einblick darauf; Es scheint, als ob onInterceptTouchEvent nicht für jedes Bewegungsereignis aufgerufen wird, wenn eine Scrollview in einem Flipper (oder einer WorkspaceView) enthalten ist.

Insbesondere das Verhalten, das ich gefunden, während eine andere Ansicht Klasse Änderung dieser sehr gleiche Problem zu beheben (es Flossen nicht eindeutig ist) war wie folgt - beachten Sie, dass diese Android ist 2.1 nur:

Wenn die Scroll lang genug ist, um zu scrollen, wird das Bewegungsereignis ACTION_DOWN von der ScrollView abgefangen und jedes nachfolgende ACTION_MOVE-Ereignis durchläuft onInterceptTouchEvent des Flippers, wo es abgefangen und entsprechend behandelt wird. In Android 2.2 tritt dieses Verhalten unabhängig von der Scrolllänge auf.

Zurück zu 2.1: Wenn die Scrollview nicht lang genug ist, zu blättern, das ACTION_DOWN Bewegungsereignis ist nicht durch die Scroll gefangen, sondern kommt zurück auf die onTouchEvent des Flippers. Alle nachfolgenden ACTION_MOVE-Ereignisse derselben Geste Überspringen Sie die onInterceptTouchEvent-Funktion und gehen Sie direkt zur onTouchEvent-Funktion!

Die Art und Weise, wie ich dies gelöst habe, war, die Funktionalität von onTouchEvent für ACTION_MOVE-Ereignisse zu übernehmen und sie in eine eigene Methode umzuwandeln. Auf diese Weise kann onTouchEvent onInterceptTouchEvent aufrufen, gefolgt von dieser Funktionalität, wenn festgestellt wird, dass das Ereignis zuvor nicht behandelt wurde.

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; 

Dies ist von WorkspaceView.java (eine Modifikation des Android Workspace.java am andro-Ansichten Projekt auf Google Code gefunden, und jetzt hier: Horizontal "tab"ish scroll between views). Für den Fall, dass wir ein Move-Ereignis erhalten und wir scrollen (was nur passiert, wenn wir uns bewusst dafür entschieden haben, es abzufangen - dh es ist in der Abfangfunktion gesetzt, also waren wir schon bei der Abfangfunktion), die wir durchführen das Bewegungsverhalten, das wir wünschen. Wenn wir hier ein Move-Ereignis erhalten und wir nicht scrollen, senden wir das Ereignis durch onIntercept zurück und sehen dann, ob wir jetzt zum Scrollen bereit sind. Wenn ja, führen wir die Aktion aus.

Es ist nicht elegant, aber es funktioniert!

Antwort

7

Ich brauchte eine neue Klasse zu erstellen, die Scrollview erweitert, und verwenden diese.

@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; 
} 

Ich habe keine Ahnung, warum, aber wenn ich versuchen, etwas zurück, aber wahr in dispatchTouchEvent (die logische Sache

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

wenn ich verstehe richtig

gewesen wäre), ist es nicht funktioniert, und dies tut.

1

Versuchen Sie android:fillViewport="true" in Ihrem Layout xml für jeden der ScrollView s. Das sagt die ScrollView so groß wie die Ansicht sein, um es in enthalten ist

+0

Es ist so auf alle Kinder eingestellt. Ich habe sogar direkt kopiert und eingefügt das XML unter http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+PlanetAndroidCom+(Planet+Android) und versuchte es als Kinderansicht. Nach einigem Herumspielen schaffte ich es, sie alle in den Viewport zu füllen. Aber kein Glück beim Rückruf, selbst wenn sie es einmal getan haben. Bisher ist keine Bildlaufleiste = kein onFling. –