2012-04-21 19 views
12

Tengo un ViewPager en el nivel raíz de una actividad.Anidamiento de Android ViewPager, deslizando ListItems dentro de un ListView horizontalmente

Cada página del localizador contiene un ListFragment (respaldado por un FragmentPagerAdapter).

Algunos de los elementos de la vista de lista deben contener adicionalmente ViewPagers para admitir deslizar el contenido de esos elementos (por ejemplo, una galería horizontal dentro de un elemento de la lista).

¿Cómo puedo anidar ver localizadores? ViewPager -> ListView (en una página) -> ViewPager (dentro de un elemento de la lista)

Puedo deslizar horizontalmente entre los ListFragments y puedo deslizar toda la lista verticalmente, pero no puedo deslizar dentro de los elementos de la lista.

Respuesta

0

No se puede anidar realmente elementos que necesitan los mismos gestos para controlarlos. Como el localizador de vista ya está capturando el movimiento horizontal, sus elementos anidados no lo captarán. Probablemente puedas hacer mucho trabajo para evitar esto al administrar el enfoque y cosas por el estilo, pero al final tu aplicación será confusa para los usuarios. Es realmente mejor no anidar elementos que usarían la misma interacción ... en este caso dos buscapersonas verán un movimiento de lado a lado.

3

Si bien no es el mejor diseño de interacción, es posible implementar este sobrescribiendo el (ev MotionEvent) dispatchTouchEvent método de la Actividad de nivel raíz y el uso de requestDisallowInterceptTouchEvent (verdadero) en el mainPager y ListView actual para evitar otro desplazamiento. Mira este ejemplo:

@Override 
public boolean dispatchTouchEvent(MotionEvent ev) { 

    Fragment listFragment = getSupportFragmentManager().findFragmentByTag(
      "android:switcher:" + R.id.pager + ":" + (mainPager.getCurrentItem())); 
    mainPager.getChildAt(mainPager.getCurrentItem()); 
    if (listFragment == null) 
     return super.dispatchTouchEvent(ev); 
    ViewPager embeddedPager = (ViewPager) listFragment.getView().findViewById(R.id.videopager); 
    if (embeddedPager != null) { 
     int[] position = new int[2]; 
     embeddedPager.getLocationOnScreen(position); 
     if (ev.getY() > position[1] && ev.getY() < position[1] + embeddedPager.getHeight()) { 
      mainPager.requestDisallowInterceptTouchEvent(true); 
      if (embeddedPager.getScrollX() % embeddedPager.getWidth() != 0) { 
       ListView listView = (ListView) listFragment.getView().findViewById(
         android.R.id.list); 
       listView.requestDisallowInterceptTouchEvent(true); 
      } 
     } 
    } 

    return super.dispatchTouchEvent(ev); 
} 
+0

Gracias por esto, he modificado ligeramente la idea para permitirle poner el código en otro lugar que no sea la función 'Activity # dispatchTouchEvent (MotionEvent)', pero la idea que utilicé fue básicamente suya :) –

11

que añade un OnTouchListener al interior ViewPager:

private OnTouchListener mSuppressInterceptListener = new OnTouchListener() { 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     if(
       event.getAction() == MotionEvent.ACTION_DOWN && 
       v instanceof ViewGroup 
     ) { 
       ((ViewGroup) v).requestDisallowInterceptTouchEvent(true); 
     } 
     return false; 
    } 
}; 

Esto sólo detecta eventos de toque ACTION_DOWN en el interior ViewPager y evita que la exterior de interceptarlo. Como devuelve false, solo se debe golpear el evento ACTION_DOWN; todos los otros eventos serán ignorados. Puede agregar este oyente a cada elemento que desee "proteger" del desplazamiento externo de ViewPager, aunque obviamente, si desea captar cualquier otro comportamiento táctil en esos elementos, tendrá que tratar con ellos dentro del oyente táctil y posiblemente implementar un mejor oyente.

Gracias a @Rodja que me dio la idea en primer lugar.

+2

Wow. Mucho más limpio. ¡Gracias! – Rodja

+0

Con mucho, la solución más fácil. – OcuS

+1

Simplemente no puedo creer lo fácil que funciona. Muchas gracias, Andrew y Rodja! –

Cuestiones relacionadas