2014-09-19 13 views
6

Pracuję nad aplikacją, która jako menu ma ViewPager. Każdy fragment ma kilka widoków podrzędnych, które mogą być ListView, ScrollView, LinearLayout, etc ... Jednym z tego fragments mają ustawień przycisk, który przełącza panel ustawień (LinearLayout otoki) z ScrollView i niektórych LinearLayout (przyciski) i SeekBar jako dzieci. Ten ustawienia panel jest animowany ze zjeżdżalnią w górę lub w dół animacji (gdy odwołany) i gdy jest to widoczne ja wyłączyć ViewPager stronicowania:Najlepszy sposób wyłączenia stronicowania ViewPager

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

Ale przyszedł z problemem, za każdym razem, gdy panel jest aż wszystko to widoki dziecko nie otrzymałby OnTouchEvent i dlatego dodałem GestureDetector.SimpleOnGestureListener:

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

i zmienił mój ViewPageronInterceptTouchEvent do:

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

To działa, przyciski panelu odbierają swoje suwaki onClick, ListView itp ... ale to nie działa tak idealnie, ponieważ Math.abs(distanceY) < Math.abs(distanceX) nie jest to dokładne. Jeśli przesuję szybko w górę iw dół lub po skosie lub jeśli dotknę przycisku z niewielkim przesunięciem, onInterceptTouchEvent zwróci true, ponieważ mGestureDetector.onTouchEvent(event) również zwróci true.

Po pewnym google natknąłem to:

viewPager.requestDisallowInterceptTouchEvent(true); 

Próbowałem coś takiego:

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

I to działa naprawdę dobrze, ponieważ ViewPager.onInterceptTouchEvent to się nazywa pierwszy z MotionEvent.ACTION_DOWN a następnie myListView.setOnTouchListener to się nazywa zaraz po i unieruchamia pozostałe akcje MotionEvent (MOVE i UP) i mogę szybko przesuwać w górę, w dół, boki, itp. Na stronie ViewPager przesuwa się, ale ListView przesuwa się jak zaklęcie.
Ale problem nadal istnieje, muszę dodać to requestDisallowInterceptTouchEvent(true) do wszystkich widoków podrzędnych onTouchEvent, a to nie jest elegancki kod.

Moje pytanie brzmi: jestem na dobrej drodze? Czy mimo to należy unikać dodawania tego słuchacza do wszystkich widoków podrzędnych panelu (oczywiście, jeśli muszę, zrobię to w sposób najbardziej ogólny)?

Dziękujemy za poświęcony czas.

Odpowiedz

16

Wyłączanie stronicowania powinno być tak proste, jak zwrot false zarówno od onInterceptTouchEvent i onTouchEvent. Nie powinieneś potrzebować dodatkowego wykrywania gestów, aby ominąć ViewPager. Rozszerz ViewPager takiego:

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

} 

używam samo (pod inną nazwą) Z tego samego powodu w jednej z moich aplikacji i na pewno działa.

+1

Jestem taki głupi, oczywiście muszę zwrócić fałszywe eheh! Jeśli zwrócę prawdę, będę kradł zdarzenia ruchu z potomków i zdarzenia nie zostaną wysłane do ViewGroup przez onTouchEvent(). Dzięki! – GuilhE

Powiązane problemy