android - studio - ¿Cómo deshabilitar el desplazamiento RecyclerView?
que es un recyclerview android (24)
No puedo desactivar el desplazamiento en
RecyclerView
.
Intenté llamar a
rv.setEnabled(false)
pero aún puedo desplazarme.
¿Cómo puedo desactivar el desplazamiento?
Añadir
android:nestedScrollingEnabled="false"
en su hijo de SrollView o NestedScrollView (y padre de ListView, recyclerview y gridview cualquiera)
Anule onTouchEvent () y onInterceptTouchEvent () y devuelva false si no necesita OnItemTouchListener. Esto no deshabilita OnClickListeners de ViewHolders.
public class ScrollDisabledRecyclerView extends RecyclerView {
public ScrollDisabledRecyclerView(Context context) {
super(context);
}
public ScrollDisabledRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public ScrollDisabledRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onTouchEvent(MotionEvent e) {
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
return false;
}
}
Así es como lo hice con el enlace de datos:
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:onTouch="@{(v,e) -> true}"/>
En lugar de "verdadero", utilicé una variable booleana que cambió en función de una condición para que la vista del reciclador cambiara entre estar deshabilitada y habilitada.
Crear clase que extienda la clase RecyclerView
public class NonscrollRecylerview extends RecyclerView {
public NonscrollRecylerview(Context context) {
super(context);
}
public NonscrollRecylerview(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public NonscrollRecylerview(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
}
Esto deshabilitará el evento de desplazamiento, pero no los eventos de clic
Use esto en su XML, haga lo siguiente:
<com.yourpackage.xyx.NonscrollRecylerview
...
...
/>
Debe anular el administrador de diseño de su vista de reciclaje para esto. De esta manera solo deshabilitará el desplazamiento, ninguna de las otras funcionalidades. Aún podrá manejar clics o cualquier otro evento táctil. Por ejemplo:-
Original:
public class CustomGridLayoutManager extends LinearLayoutManager {
private boolean isScrollEnabled = true;
public CustomGridLayoutManager(Context context) {
super(context);
}
public void setScrollEnabled(boolean flag) {
this.isScrollEnabled = flag;
}
@Override
public boolean canScrollVertically() {
//Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll
return isScrollEnabled && super.canScrollVertically();
}
}
Aquí, usando el indicador "isScrollEnabled", puede habilitar / deshabilitar la funcionalidad de desplazamiento de su vista de reciclaje temporalmente.
También:
Simplemente anule su implementación existente para deshabilitar el desplazamiento y permitir hacer clic.
linearLayoutManager = new LinearLayoutManager(context) {
@Override
public boolean canScrollVertically() {
return false;
}
};
Encontré un fragmento que contiene múltiples RecycleView, por lo que solo necesito una barra de desplazamiento en lugar de una barra de desplazamiento en cada RecycleView.
Así que acabo de poner el ScrollView en el contenedor principal que contiene los 2 RecycleViews y uso
android:isScrollContainer="false"
en el RecycleView
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="LinearLayoutManager"
android:isScrollContainer="false" />
Escribió una versión de Kotlin:
class NoScrollLinearLayoutManager(context: Context?) : LinearLayoutManager(context) {
private var scrollable = true
fun enableScrolling() {
scrollable = true
}
fun disableScrolling() {
scrollable = false
}
override fun canScrollVertically() =
super.canScrollVertically() && scrollable
override fun canScrollHorizontally() =
super.canScrollVertically()
&& scrollable
}
uso:
recyclerView.layoutManager = NoScrollLinearLayoutManager(context)
(recyclerView.layoutManager as NoScrollLinearLayoutManager).disableScrolling()
Esta es una solución un poco complicada pero funciona;
puede habilitar / deshabilitar el desplazamiento en
RecyclerView
.
Este es un
RecyclerView.OnItemTouchListener
vacío.
RecyclerView.OnItemTouchListener
roba cada evento táctil y deshabilita el
RecyclerView
objetivo.
RecyclerView rv = ...
RecyclerView.OnItemTouchListener disabler = new RecyclerViewDisabler();
rv.addOnItemTouchListener(disabler); // disables scolling
// do stuff while scrolling is disabled
rv.removeOnItemTouchListener(disabler); // scrolling is enabled again
Utilizándolo:
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="true"
android:nestedScrollingEnabled="false"
tools:listitem="@layout/adapter_favorite_place">
Esto funciona para mi:
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
Extienda el
LayoutManager
y anule
canScrollHorizontally()
y
canScrollVertically()
para deshabilitar el desplazamiento.
Tenga en cuenta que insertar elementos al principio no se desplazará automáticamente hacia el principio, para evitar esto haga algo como:
private void clampRecyclerViewScroll(final RecyclerView recyclerView)
{
recyclerView.getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver()
{
@Override
public void onItemRangeInserted(int positionStart, int itemCount)
{
super.onItemRangeInserted(positionStart, itemCount);
// maintain scroll position at top
if (positionStart == 0)
{
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{
((GridLayoutManager) layoutManager).scrollToPositionWithOffset(0, 0);
}else if(layoutManager instanceof LinearLayoutManager)
{
((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(0, 0);
}
}
}
});
}
Hay una forma más directa de deshabilitar el desplazamiento (técnicamente es más bien la intercepción de un evento de desplazamiento y finalizarlo cuando se cumple una condición), utilizando solo la funcionalidad estándar.
RecyclerView
tiene el método llamado
addOnScrollListener(OnScrollListener listener)
, y con solo esto puede evitar que se desplace, así:
<android.support.v7.widget.RecyclerView
android:background="#ffffff"
android:id="@+id/myrecycle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="false">
Caso de uso:
supongamos que desea deshabilitar el desplazamiento cuando hace clic en uno de los elementos dentro de
RecyclerView
para poder realizar algunas acciones con él, sin distraerse desplazándose accidentalmente a otro elemento, y cuando haya terminado con él, simplemente haga clic en el elemento nuevamente para habilitar el desplazamiento.
Para eso, querrá adjuntar
OnClickListener
a cada elemento dentro de
RecyclerView
, por lo que cuando hace clic en un elemento, alternaría
isItemSelected
de
false
a
true
.
De esta manera, cuando intente desplazarse,
RecyclerView
llamará automáticamente al método
onScrollStateChanged
y dado que
isItemSelected
establece en
true
, se detendrá inmediatamente, antes de que
RecyclerView
tenga la oportunidad, bueno ... de desplazarse.
Nota: para una mejor usabilidad, intente usar
GestureListener
lugar de
OnClickListener
para evitar clics
accidental
.
Hay una respuesta realmente simple.
public class RecyclerViewDisabler implements RecyclerView.OnItemTouchListener {
boolean isEnable = true;
public RecyclerViewDisabler(boolean isEnable) {
this.isEnable = isEnable;
}
public boolean isEnable() {
return isEnable;
}
public void setEnable(boolean enable) {
isEnable = enable;
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
return !isEnable;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept){}
}
El código anterior deshabilita el desplazamiento vertical de RecyclerView.
He estado luchando en este problema durante una hora, por lo que me gustaría compartir mi experiencia. Para la solución layoutManager está bien, pero si desea volver a habilitar el desplazamiento, el reciclador volverá al principio.
La mejor solución hasta ahora (al menos para mí) es usar el método @Zsolt Safrany pero agregar getter y setter para que no tenga que quitar o agregar OnItemTouchListener.
De la siguiente manera
RecyclerViewDisabler disabler = new RecyclerViewDisabler(true);
feedsRecycler.addOnItemTouchListener(disabler);
// TO ENABLE/DISABLE JUST USE THIS
disabler.setEnable(enable);
Uso
LinearLayoutManager lm = new LinearLayoutManager(getContext()) {
@Override
public boolean canScrollVertically() {
return false;
}
};
La respuesta REAL REAL es: Para API 21 y superior:
No se necesita código java.
Puede configurar
android:nestedScrollingEnabled="false"
en xml:
public class RecyclerViewDisabler implements RecyclerView.OnItemTouchListener {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
return true;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
La verdadera respuesta es
recyclerView.setNestedScrollingEnabled(false);
Más información en la documentation
Otra alternativa es
setLayoutFrozen
, pero viene con muchos otros efectos secundarios.
Por alguna razón, la respuesta de @Alejandro Gracia comienza a funcionar solo después de unos segundos.
Encontré una solución que bloquea el RecyclerView instantáneamente:
recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
return true;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
Puede agregar esta línea después de configurar su adaptador
ViewCompat.setNestedScrollingEnabled(recyclerView, false);
Ahora su vista de reciclaje funcionará con desplazamiento suave
Puede deshabilitar el desplazamiento congelando su RecyclerView.
Para congelar:
recyclerView.setLayoutFrozen(true)
Para descongelar:
recyclerView.setLayoutFrozen(false)
Sé que esto ya tiene una respuesta aceptada, pero la solución no tiene en cuenta un caso de uso que encontré.
Específicamente, necesitaba un elemento de encabezado en el que todavía se pudiera hacer clic, pero deshabilité el mecanismo de desplazamiento de RecyclerView. Esto se puede lograr con el siguiente código:
recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
return e.getAction() == MotionEvent.ACTION_MOVE;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
Si solo deshabilita la
funcionalidad
de
desplazamiento
de
RecyclerView
, puede usar
setLayoutFrozen(true);
Método de
RecyclerView
.
Pero no se puede desactivar el evento táctil.
your_recyclerView.setLayoutFrozen(true);
Simplemente agregue esto a su vista de reciclaje en xml
android:descendantFocusability="blocksDescendants"
Me gusta esto
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (viewModel.isItemSelected) {
recyclerView.stopScroll();
}
}
});
en XML: -
Puedes añadir
android:nestedScrollingEnabled="false"
en el archivo XML de diseño RecyclerView secundario
o
en Java: -
childRecyclerView.setNestedScrollingEnabled(false);
a su RecyclerView en código Java.
Usando ViewCompat (Java): -
childRecyclerView.setNestedScrollingEnabled(false);
solo funcionará en
android_version> 21
dispositivos.
para trabajar en todos los dispositivos use lo siguiente
ViewCompat.setNestedScrollingEnabled(childRecyclerView, false);
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
// Stop only scrolling.
return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING;
}
});