2014-09-19 17 views
6

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 ViewPageronInterceptTouchEvent 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.

risposta

16

Disattivare il paging dovrebbe essere semplice come restituire false da entrambi onInterceptTouchEvent e onTouchEvent. Non è necessario alcun rilevamento di gesture aggiuntivo per aggirare lo ViewPager. Estendere ViewPager come questo:

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

} 

Io uso la stessa cosa (con un nome diverso) per lo stesso motivo in una delle mie applicazioni e funziona sicuramente.

+1

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

Problemi correlati