Sto sviluppando un'applicazione che ha un ViewPager
come un menu. Ogni fragment
ha un sacco di punti di vista del bambino che può essere ListView
, ScrollView
, LinearLayout
, ecc ... Uno di questo fragments
hanno un impostazioni pulsante che commuta un pannello delle impostazioni (LinearLayout
involucro) con un ScrollView
e alcune LinearLayout
(tasti) e SeekBar
come bambini. Questo impostazioni pannello è animato con uno scivolo alto o in basso di animazione (quando licenziato) e quando è visibile ho disattivare il ViewPager
paging:Il modo migliore per disabilitare l'impaginazione 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;
}
Ma questo è venuto con un problema, ogni volta che il pannello è su tutto ciò che viste bambino non sarebbe ricevere il OnTouchEvent
ed è per questo ho aggiunto un 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);
}
}
e cambiato la mia ViewPager
onInterceptTouchEvent
a:
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (!pagingEnabled && event.getAction() == MotionEvent.ACTION_MOVE && (mGestureDetector != null && mGestureDetector.onTouchEvent(event))) {
return true;
}
return super.onInterceptTouchEvent(event);
}
Questo funziona, i pulsanti del pannello ricevono il loro onClick, i controlli ListView, ecc ... ma questo non funziona in modo perfetto perché Math.abs(distanceY) < Math.abs(distanceX)
non è così preciso. Se faccio scorrere rapidamente verso l'alto o verso il basso o diagonalmente o se tocco un pulsante con uno scorrimento minore, lo onInterceptTouchEvent
restituirà true
perché restituirà anche true
.
Dopo qualche ricerca su google mi sono imbattuto in questo:
viewPager.requestDisallowInterceptTouchEvent(true);
e ho cercato qualcosa di simile:
myListView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
viewPager.requestDisallowInterceptTouchEvent(true);
return false;
}
});
e funziona davvero bene perché ViewPager.onInterceptTouchEvent
si chiama dapprima con MotionEvent.ACTION_DOWN
e poi myListView.setOnTouchListener
Si chiama subito dopo e non consente le restanti azioni MotionEvent
(MOVE e UP) e posso scorrere rapidamente verso l'alto, verso il basso, i lati, ecc. La pagina non viene aperta ma lo ListView
striscia come un incantesimo.
Ma rimane ancora un problema, devo aggiungere questo requestDisallowInterceptTouchEvent(true)
a tutte le viste figlio onTouchEvent
, e non è un codice elegante.
Quindi la mia domanda è: sono sulla strada giusta? C'è comunque da evitare di aggiungere questo listener a tutte le viste child del pannello (ovviamente se devo farlo lo farò nel modo più generico)?
Grazie per il vostro tempo.
Sono così stupido, certo che devo restituire il falso eheh! Se restituisco true ruberò gli eventi di movimento dai bambini e gli eventi non verranno inviati al ViewGroup tramite onTouchEvent(). Grazie! – GuilhE