Cómo deshabilitar el desplazamiento de RecyclerView excepto programáticamente

Tengo un RecyclerView con un LinearLayoutManager en la orientación HORIZONTAL . Cada elemento en él puede tener elementos interactivos (incluyendo ScrollView vertical s). ¿Existe una manera de hacer que el RecyclerView ignore los intentos del usuario de desplazar o lanzar el RecyclerView horizontalmente sin interceptar eventos táctiles a los niños?

Estoy programáticamente controlando el desplazamiento del RecyclerView que funciona muy bien hasta que el usuario lo lance.

He intentado algo muy simple donde la idea es cuando llamo a smoothScrollToPosition en respuesta a algún evento, permito desplazar y deshabilitar eventos de toque hasta que se resuelve el desplazamiento. Me gusta esto:

  private class NoScrollHorizontalLayoutManager extends LinearLayoutManager { ScrollingTouchInterceptor interceptor = new ScrollingTouchInterceptor(); protected boolean canScroll; public NoScrollHorizontalLayoutManager(Context ctx) { super(ctx, LinearLayoutManager.HORIZONTAL, false); } public RecyclerView.OnItemTouchListener getInterceptor() { return interceptor; } @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { canScroll = true; super.smoothScrollToPosition(recyclerView, state, position); } @Override public void onScrollStateChanged(int state) { super.onScrollStateChanged(state); if(state == RecyclerView.SCROLL_STATE_IDLE) { canScroll = false; } } @Override public boolean canScrollHorizontally() { return canScroll; } public class ScrollingTouchInterceptor implements RecyclerView.OnItemTouchListener { @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { return canScrollHorizontally(); } @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } } } 

Y usarlo así ..

 NoScrollHorizontalLayoutManager layout = new NoScrollHorizontalLayoutManager(context); recycler.setLayoutManager(layout); recycler.addOnItemTouchListener(layout.getInterceptor()); 

Que en realidad casi funciona … pero todavía puedo arruinar el desplazamiento programático tocando la pantalla cuando el desplazamiento suave está en movimiento. Claramente estoy perdiendo algo obvio o hay una manera mucho más inteligente de hacer esto.

ACTUALIZAR la solución no-RecyclerView se encontró aquí: ¿Cómo deshabilitar la paginación por deslizamiento con el dedo en ViewPager, pero sigue siendo capaz de deslizar por programación?

 /** * ViewPager that doesn't allow swiping. */ public class NonSwipeableViewPager extends ViewPager { public NonSwipeableViewPager(Context context) { super(context); } public NonSwipeableViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { // Never allow swiping to switch between pages return false; } @Override public boolean onTouchEvent(MotionEvent event) { // Never allow swiping to switch between pages return false; } } 

 android:nestedScrollingEnabled="false" 

Haga lo anterior en el archivo xml, en el RecyclerView TAG.

Lo primero, no creo que esto sea alcanzable de forma no programática.

Camino 1: Simple – Deshabilita la otra vista basada en el toque.

Si el usuario toca al padre, deshabilita el desplazamiento de las vistas secundarias. Viceversa también

Pieza de código para hacer esto

 recyclerView.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View p_v, MotionEvent p_event) { yourChildView.getParent().requestDisallowInterceptTouchEvent(false); return false; } }); 

Camino 2: Puesto que usted está teniendo pequeños problemas en su implementación. Si lo publicas, alguien puede solucionarlo también.

Anulando onInterceptTouchEvent evita el comportamiento de stop on click.

 @Override public boolean onInterceptTouchEvent(MotionEvent e) { return false; } 
 recyclerView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; } }); 
  recyclerView.setNestedScrollingEnabled(false); 

Para obtener más información, consulte la documentación .

Esto da el efecto de la continuidad.

 recyclerView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN) { recyclerView.smoothScrollToPosition(position); return true; } else if (action == MotionEvent.ACTION_UP) { recyclerView.smoothScrollToPosition(position); return true; } return false; } }); 
  • ¿Cómo implementar multi-select en RecyclerView?
  • Admob Native Ads dentro de un Recylerview muestra espacio en blanco antes de cargar
  • Decoración de artículos de RecyclerView
  • Android - Cómo detener la recarga de imágenes en Recyclerview al desplazarse
  • RecyclerView & SnapHelper -> obtener una vista rápida / segmentada
  • Cómo obtener el elemento del adaptador RecyclerView en Android
  • RecyclerView cortar el último artículo
  • Recyclerview desplazamiento pasado FAB
  • RecyclerView add EmptyView
  • Crear menú de opciones para RecyclerView-Item
  • Android TV RecyclerView interacción con el foco
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.