android android-viewpager gesture swiperefreshlayout

android - SwipeRefreshLayout+ViewPager, ¿limita el desplazamiento horizontal solamente?



android-viewpager gesture (6)

Basé esto en una respuesta anterior pero encontré que esto funcionaba un poco mejor. La moción comienza con un evento ACTION_MOVE y termina en ACTION_UP o ACTION_CANCEL en mi experiencia.

mViewPager.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: mSwipeRefreshLayout.setEnabled(false); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mSwipeRefreshLayout.setEnabled(true); break; } return false; } });

Implementé SwipeRefreshLayout y ViewPager en mi aplicación, pero hay un gran problema: cada vez que voy a desplazarme hacia la izquierda / derecha para alternar entre las páginas, el desplazamiento es demasiado delicado. Un pequeño deslizamiento hacia abajo activará la actualización SwipeRefreshLayout también.

Quiero establecer un límite para cuando se inicie el deslizamiento horizontal, luego forzarlo horizontalmente solo hasta que pase el deslizamiento. En otras palabras, quiero cancelar el desplazamiento vertical cuando el dedo se mueve horizontalmente.

Este problema solo ocurre en ViewPager , si ViewPager hacia abajo y se SwipeRefreshLayout la función de refresco SwipeRefreshLayout (se muestra la barra) y luego muevo mi dedo horizontalmente, todavía solo permite deslizamientos verticales.

Intenté extender la clase ViewPager pero no funciona en absoluto:

public class CustomViewPager extends ViewPager { public CustomViewPager(Context ctx, AttributeSet attrs) { super(ctx, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { boolean in = super.onInterceptTouchEvent(ev); if (in) { getParent().requestDisallowInterceptTouchEvent(true); this.requestDisallowInterceptTouchEvent(true); } return false; } }

Layout xml:

<android.support.v4.widget.SwipeRefreshLayout android:id="@+id/viewTopic" android:layout_width="match_parent" android:layout_height="match_parent"> <com.myapp.listloader.foundation.CustomViewPager android:id="@+id/topicViewPager" android:layout_width="match_parent" android:layout_height="match_parent"/> </android.support.v4.widget.SwipeRefreshLayout>

Cualquier ayuda será apreciada, gracias


Hay un problema con la solución de nhasan:

Si el deslizamiento horizontal que desencadena la setEnabled(false) en SwipeRefreshLayout en OnPageChangeListener ocurre cuando SwipeRefreshLayout ya ha reconocido un Pull-to-Reload pero aún no ha llamado a la notificación de devolución de llamada, la animación desaparece pero el estado interno de SwipeRefreshLayout se mantiene "refrescante" para siempre ya que no se llaman devoluciones de llamadas de notificación que podrían restablecer el estado. Desde la perspectiva del usuario, esto significa que Pull-to-Reload ya no funciona, ya que no se reconocen todos los gestos de extracción.

El problema aquí es que la llamada de disable(false) elimina la animación de la ruleta y se llama a la devolución de llamada de notificación desde el método onAnimationEnd de un AnimationListener interno para esa ruleta que está onAnimationEnd de esa manera.

Fue necesario que nuestro examinador con los dedos más rápidos provocara esta situación, pero también puede suceder de vez en cuando en escenarios realistas.

Una solución para solucionar esto es anular el método SwipeRefreshLayout en SwipeRefreshLayout siguiente manera:

public class MySwipeRefreshLayout extends SwipeRefreshLayout { private boolean paused; public MySwipeRefreshLayout(Context context) { super(context); setColorScheme(); } public MySwipeRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); setColorScheme(); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (paused) { return false; } else { return super.onInterceptTouchEvent(ev); } } public void setPaused(boolean paused) { this.paused = paused; } }

Use MySwipeRefreshLayout en su Diseño - Archivo y cambie el código en la solución de mhasan a

... @Override public void onPageScrollStateChanged(int state) { swipeRefreshLayout.setPaused(state != ViewPager.SCROLL_STATE_IDLE); } ...


He encontrado tu problema. Personalizar SwipeRefreshLayout resolvería el problema.

public class CustomSwipeToRefresh extends SwipeRefreshLayout { private int mTouchSlop; private float mPrevX; public CustomSwipeToRefresh(Context context, AttributeSet attrs) { super(context, attrs); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPrevX = MotionEvent.obtain(event).getX(); break; case MotionEvent.ACTION_MOVE: final float eventX = event.getX(); float xDiff = Math.abs(eventX - mPrevX); if (xDiff > mTouchSlop) { return false; } } return super.onInterceptTouchEvent(event); }

Ver la referencia: link


No estoy seguro de si todavía tiene este problema, pero la aplicación Google I / O apilada resuelve este problema de la siguiente manera:

viewPager.addOnPageChangeListener( new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled( int position, float v, int i1 ) { } @Override public void onPageSelected( int position ) { } @Override public void onPageScrollStateChanged( int state ) { enableDisableSwipeRefresh( state == ViewPager.SCROLL_STATE_IDLE ); } } ); private void enableDisableSwipeRefresh(boolean enable) { if (swipeContainer != null) { swipeContainer.setEnabled(enable); } }

He usado el mismo y funciona bastante bien.

EDITAR: Use addOnPageChangeListener () en lugar de setOnPageChangeListener ().


Por alguna razón que solo ellos conocen mejor, el equipo de desarrolladores de la biblioteca de soporte consideró oportuno interceptar con fuerza todos los eventos de movimiento vertical de arrastre del diseño infantil de SwipeRefreshLayout , incluso cuando un niño solicita específicamente la propiedad del evento. Lo único que comprueban es que el estado de desplazamiento vertical de su hijo principal está en cero (en el caso de que su hijo sea verticalmente desplazable). El método requestDisallowInterceptTouchEvent() ha sido anulado con un cuerpo vacío, y el (no tan) esclarecedor comentario "Nope".

La forma más sencilla de resolver este problema sería copiar la clase de la biblioteca de soporte en su proyecto y eliminar la anulación del método. La implementación de ViewGroup usa un estado interno para manejar onInterceptTouchEvent() , por lo que no puede simplemente sobrescribir el método nuevamente y duplicarlo. Si realmente desea anular la implementación de la biblioteca de soporte, deberá configurar un indicador personalizado en las llamadas a requestDisallowInterceptTouchEvent() y anular el onInterceptTouchEvent() y onTouchEvent() (o posiblemente hackear el canChildScrollUp() ) en función de eso.


Resuelto de manera muy simple sin extender nada

mPager.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { mLayout.setEnabled(false); switch (event.getAction()) { case MotionEvent.ACTION_UP: mLayout.setEnabled(true); break; } return false; } });

trabajar como un encanto