2014-09-19 7 views
6

Ich entwickle eine App, die eine ViewPager als Menü haben. Jede fragment hat eine Reihe von Kindern Ansichten, die ListView sein können, ScrollView, LinearLayout, etc ... Einer dieser fragments hat einen Einstellungen Knopf, schaltet ein Einstellungsfeld (LinearLayout Wrapper) mit einem ScrollView und einigen LinearLayout (Tasten) und SeekBar als Kinder. Diese Einstellungen Panel mit einer Folie nach oben oder nach unten Animation animiert wird (wenn entlassen) und, wenn es sichtbar ist deaktiviere ich das ViewPager Paging:Die beste Möglichkeit zum Deaktivieren von ViewPager Paging

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if (!pagingEnabled && event.getAction() == MotionEvent.ACTION_MOVE) { 
     return true; 
    } 
    return super.onTouchEvent(event); 
} 

@Override 
public boolean onInterceptTouchEvent(MotionEvent event) { 
    if (!pagingEnabled && event.getAction() == MotionEvent.ACTION_MOVE) { 
     return true; 
    } 
    return super.onInterceptTouchEvent(event); 
} 

public boolean isPagingEnabled() { 
    return pagingEnabled; 
} 

public void setPagingEnabled(boolean pagingEnabled) { 
    this.pagingEnabled = pagingEnabled; 
} 

Aber das kam mit einem Problem, das Panel jeder Zeit abgelaufen ist alles was man Kind Blick würde die OnTouchEvent nicht erhalten, und deshalb habe ich eine GestureDetector.SimpleOnGestureListener hinzugefügt:

protected class YScrollDetector extends GestureDetector.SimpleOnGestureListener { 
    @Override 
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 
     Log.i(C.TAG, "distanceX " + distanceX + " distanceY " + distanceY); 
     return Math.abs(distanceY) < Math.abs(distanceX); 
    } 
} 

und änderte mein ViewPageronInterceptTouchEvent zu:

@Override 
public boolean onInterceptTouchEvent(MotionEvent event) { 
    if (!pagingEnabled && event.getAction() == MotionEvent.ACTION_MOVE && (mGestureDetector != null && mGestureDetector.onTouchEvent(event))) { 
     return true; 
    } 
    return super.onInterceptTouchEvent(event); 
} 

Das funktioniert, die Panel-Tasten erhalten ihre onClick, die ListView Swipes, etc ... aber das funktioniert nicht so perfekt, weil Math.abs(distanceY) < Math.abs(distanceX) es nicht so genau ist. Wenn ich schnell auf und ab wische oder diagonal wische oder wenn ich einen Knopf mit einem kleinen Swipe berühre, gibt onInterceptTouchEventtrue zurück, weil mGestureDetector.onTouchEvent(event) auch true zurückgibt.

Nach einiger Google-Suche stieß ich auf diese:

viewPager.requestDisallowInterceptTouchEvent(true); 

Und ich versuchte, so etwas wie dieses:

myListView.setOnTouchListener(new View.OnTouchListener() { 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     viewPager.requestDisallowInterceptTouchEvent(true); 
     return false; 
    } 
}); 

Und es funktioniert wirklich gut, weil ViewPager.onInterceptTouchEvent es mit MotionEvent.ACTION_DOWN zuerst genannt wird und dann myListView.setOnTouchListener es heißt direkt nach und verbietet die verbleibenden MotionEvent Aktionen (MOVE und UP) und ich kann schnell nach oben, unten, Seitenwege, etc. wischen. Die ViewPager wont Seite aber die ListView wischt wie ein Charme.

Aber ein Problem bleibt immer noch, ich muss diese requestDisallowInterceptTouchEvent(true) zu allen untergeordneten Ansichten onTouchEvent hinzufügen, und es ist nicht eleganter Code.

Also meine Frage ist, ich bin auf dem richtigen Weg? Gibt es trotzdem, diesen Zuhörer zu allen Panel-Kind-Ansichten hinzuzufügen (natürlich, wenn ich es tun muss, mache ich das auf die allgemeinste Art)?

Danke für Ihre Zeit.

Antwort

16

Die Deaktivierung des Paging sollte so einfach sein wie die Rückgabe false von onInterceptTouchEvent und onTouchEvent. Sie sollten keine zusätzliche Gestenerkennung benötigen, um die ViewPager zu umgehen. Extend ViewPager wie folgt aus:

public class MyViewPager extends ViewPager { 
    private boolean pagingEnabled = true; 

    public MyViewPager(Context context) { 
     super(context); 
    } 

    public MyViewPager(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public void setPagingEnabled(boolean pagingEnabled) { 
     this.pagingEnabled = pagingEnabled; 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent event) { 
     return pagingEnabled && super.onInterceptTouchEvent(event); 
    } 

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

} 

ich die gleiche Sache verwenden (mit einem anderen Namen) aus dem gleichen Grund in einem meiner apps und es funktioniert auf jeden Fall.

+1

Ich bin so dumm, natürlich muss ich falsch eheh zurück! Wenn ich "true" zurückmelde, stehlen wir die Bewegungsereignisse von den Kindern und die Ereignisse werden nicht über onTouchEvent() an die ViewGroup gesendet. Vielen Dank! – GuilhE