Estoy usando el nuevo CoordinatorLayout con AppBarLayout y CollapsingToolbarLayout. Debajo de AppBarLayout, tengo un RecyclerView con una lista de contenido.
He verificado que el desplazamiento de volteo funciona en RecyclerView cuando me desplazo hacia arriba y hacia abajo en la lista. Sin embargo, también me gustaría que AppBarLayout se desplace suavemente durante la expansión.
Al desplazarse hacia arriba para expandir CollaspingToolbarLayout, el desplazamiento se detiene inmediatamente una vez que levanta el dedo de la pantalla. Si se desplaza hacia arriba en un movimiento rápido, a veces el CollapsingToolbarLayout vuelve a contraerse también. Este comportamiento con RecyclerView parece funcionar de manera muy diferente que cuando se usa un NestedScrollView.
Intenté establecer diferentes propiedades de desplazamiento en la vista del reciclador, pero no he podido resolver esto.
Aquí hay un video que muestra algunos de los problemas de desplazamiento. https://youtu.be/xMLKoJOsTAM
Aquí hay un ejemplo que muestra el problema con RecyclerView (CheeseDetailActivity). https://github.com/tylerjroach/cheesesquare
Aquí está el ejemplo original que usa un NestedScrollView de Chris Banes. https://github.com/chrisbanes/cheesesquare
Respuestas:
La respuesta de Kirill Boyarshinov fue casi correcta.
El problema principal es que RecyclerView a veces da una dirección de lanzamiento incorrecta, por lo que si agrega el siguiente código a su respuesta, funciona correctamente:
Espero que esto ayude.
fuente
if (target instanceof SwipeRefreshLayout && velocityY < 0) { target = ((SwipeRefreshLayout) target).getChildAt(0); }
antesif (target instanceof RecyclerView && velocityY < 0) {
Parece que
v23
actualización aún no lo solucionó.He encontrado una especie de truco para arreglarlo con el lanzamiento. El truco consiste en reanudar el evento de lanzamiento si el hijo superior de ScrollingView está cerca del comienzo de los datos en el Adaptador.
Úselo en su diseño así:
EDITAR: La reanudación de eventos de lanzamiento ahora se basa en
verticalScrollOffset
lugar de la cantidad de elementos desde la parte superior deRecyclerView
.EDIT2: Verifique el destino como
ScrollingView
instancia de interfaz en lugar deRecyclerView
. AmbosRecyclerView
eNestedScrollingView
implementarlo.fuente
verticalScrollOffset
que es más general. Ahora el evento de lanzamiento se reanudará cuandorecyclerView
se desplace hacia arriba.target instanceof RecyclerView
totarget instanceof NestedScrollView
, or more for genérico case totarget instanceof ScrollingView
. Actualicé la respuesta.He encontrado la solución aplicando OnScrollingListener al recyclerView. ahora funciona muy bien El problema es que la vista de reciclaje proporcionó el valor de consumo incorrecto y el comportamiento no sabe cuándo la vista de reciclaje se desplaza hacia arriba.
fuente
CoordinatorLayout
yViewPager
muchas gracias por esta solución tan esperada. Escriba un GIST para el mismo para que otros desarrolladores también puedan beneficiarse de él. Estoy compartiendo esta solución también. Gracias de nuevo.Se ha solucionado desde el diseño de soporte 26.0.0.
fuente
Esta es una versión fluida de Google Support Design AppBarLayout. Si está utilizando AppBarLayout, sabrá que tiene un problema con fling.
Ver Biblioteca aquí .. https://github.com/henrytao-me/smooth-app-bar-layout
fuente
Es un error de la vista de reciclaje. Se supone que está arreglado en v23.1.0.
mira https://code.google.com/p/android/issues/detail?id=177729
fuente
v26.0.1
!Este es mi diseño y el desplazamiento está funcionando como debería.
fuente
Mi solución hasta ahora, basada en las respuestas de Mak Sing y Manolo García .
No es totalmente perfecto. Por ahora no sé cómo volver a calcular una velocidad de valide para evitar un efecto extraño: la barra de aplicaciones puede expandirse más rápido que la velocidad de desplazamiento. Pero no se puede alcanzar el estado con una barra de aplicaciones expandida y una vista de reciclador desplazada.
fuente
Field viewFlingerField = recyclerView.getClass().getDeclaredField("mViewFlinger"); viewFlingerField.setAccessible(true); Object flinger = viewFlingerField.get(recyclerView); Field scrollerField = flinger.getClass().getDeclaredField("mScroller"); scrollerField.setAccessible(true); ScrollerCompat scroller = (ScrollerCompat) scrollerField.get(flinger); velocity = Math.signum(mVelocity) * Math.abs(scroller.getCurrVelocity());
En mi caso, estaba teniendo el problema de que el lanzamiento
RecyclerView
no lo desplazaría suavemente, haciendo que se atascara.Esto fue porque, por alguna razón, había olvidado que había puesto mi
RecyclerView
en unNestedScrollView
.Es un error tonto, pero me tomó un tiempo resolverlo ...
fuente
Agrego una vista de 1dp de altura dentro de AppBarLayout y luego funciona mucho mejor. Este es mi diseño.
fuente
Ya hay algunas soluciones bastante populares aquí, pero después de jugar con ellas, encontré una solución bastante simple que funcionó bien para mí. Mi solución también garantiza que
AppBarLayout
solo se expanda cuando el contenido desplazable llega a la cima, una ventaja sobre otras soluciones aquí.fuente
La respuesta aceptada no funcionó para mí porque tenía
RecyclerView
dentro de aSwipeRefreshLayout
y aViewPager
. Esta es la versión mejorada que busca unRecyclerView
en la jerarquía y debería funcionar para cualquier diseño:fuente
Respuesta: se solucionó en la biblioteca de soporte v26
pero v26 tiene algún problema al lanzar. A veces, AppBar se recupera de nuevo incluso si el lanzamiento no es demasiado difícil.
¿Cómo elimino el efecto de rebote en la barra de aplicaciones?
Si encuentra el mismo problema al actualizar para admitir v26, aquí está el resumen de esta respuesta .
fuente
Julian Os tiene razón.
La respuesta de Manolo García no funciona si la vista del reciclador está por debajo del umbral y se desplaza. Debe comparar la vista
offset
del reciclador y lavelocity to the distance
posición del artículo, no la del artículo.Hice la versión de Java refiriéndome al código de Kotlin de Julian y restando la reflexión.
fuente
BaseApplication
He encontrado la solución por Eniz Bilgin https://stackoverflow.com/a/45090239/7639018
El problema se ha resuelto con las bibliotecas en este repositorio.
( https://developer.android.com/topic/libraries/support-library/setup.html )
fuente
Con referencia al rastreador de problemas de Google , se ha solucionado con la versión de Android 26.0.0-beta2 de la biblioteca de soporte
Actualice su biblioteca de soporte de Android versión 26.0.0-beta2.
Si persiste algún problema, informe en el rastreador de problemas de Google que volverán a abrir para examinarlo.
fuente
Agregar otra respuesta aquí ya que las anteriores no satisfacían completamente mis necesidades o no funcionaban muy bien. Este se basa parcialmente en ideas difundidas aquí.
Entonces, ¿qué hace este?
Escenario hacia abajo: si AppBarLayout está colapsado, permite que RecyclerView se ejecute por sí solo sin hacer nada. De lo contrario, colapsa AppBarLayout y evita que RecyclerView realice su lanzamiento. Tan pronto como se colapsa (hasta el punto que demanda la velocidad dada) y si queda velocidad, el RecyclerView se lanza con la velocidad original menos lo que AppBarLayout acaba de consumir colapso.
Lanzamiento ascendente del escenario: si el desplazamiento de desplazamiento del RecyclerView no es cero, se lanza con la velocidad original. Tan pronto como termine eso y si aún queda velocidad (es decir, el RecyclerView se desplaza a la posición 0), el AppBarLayout se expande hasta el punto que la velocidad original menos las demandas recién consumidas. De lo contrario, AppBarLayout se expande hasta el punto que exige la velocidad original.
AFAIK, este es el comportamiento indended.
Hay mucha reflexión involucrada, y es bastante personalizada. No se encontraron problemas todavía. También está escrito en Kotlin, pero entenderlo no debería ser un problema. Puede usar el complemento IntelliJ Kotlin para compilarlo en bytecode -> y descompilarlo de nuevo en Java. Para usarlo, colóquelo en el paquete android.support.v7.widget y configúrelo como el comportamiento de CoordinadorLayout.LayoutParams de AppBarLayout en el código (o agregue el constructor xml aplicable o algo así)
fuente
Esta es mi solución en mi proyecto.
simplemente detenga el mScroller cuando obtenga Action_Down
xml:
FixAppBarLayoutBehavior.java:
fuente
para androidx,
Si su archivo de manifiesto tiene una línea android: hardwareAccelerated = "false", elimínela.
fuente