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.
- Confirmación y eliminación de deshacer en RecyclerView
- Recyclerview lag en desplazamiento debido a los anuncios de Admob
- LinearLayoutManager setOrientation después de rotación del teléfono no funciona
- Mostrar la vista personalizada bajo el elemento RecyclerView deslizado
- ¿Cómo tener un ListView / RecyclerView dentro de un RecyclerView padre?
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; } }
- Cómo cambiar el diseño del elemento recyclerview desde fuera?
- NotifyDataSetChanged no actualiza RecyclerView
- RecyclerView se bloquea cuando "las vistas desechadas o conectadas no se pueden reciclar"
- RecyclerView: Las clases internas no pueden tener una declaración estática
- Recyclerview Sin adaptador conectado; Saltar el diseño
- GridLayoutManager setSpanCount no funciona en OnClickListener de un botón
- RecyclerView - Obtener una vista en posición particular
- ¿Cómo usar RecyclerView dentro de NestedScrollView?
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; } });
- Google Analytics V4 con dispositivos Amazon
- Cómo utilizar Intent.ACTION_APP_ERROR como medio para un marco de "retroalimentación" en Android?