Solución:
EDITAR Como se señaló en los comentarios, mi respuesta ahora está desactualizada, consulte https://stackoverflow.com/a/58272283/4291272
Ya sea que esté utilizando un CoordinatorLayout
o no, un RecyclerView.OnScrollListener
parece el camino correcto a seguir en lo que respecta a la elevación. Sin embargo, desde mi experiencia recyclerview.getChild(0).getTop()
no es confiable y debería no utilizarse para determinar el estado de desplazamiento. En cambio, esto es lo que está funcionando:
private static final int SCROLL_DIRECTION_UP = -1;
// ...
// Put this into your RecyclerView.OnScrollListener > onScrolled() method
if (recyclerview.canScrollVertically(SCROLL_DIRECTION_UP)) {
// Remove elevation
toolbar.setElevation(0f);
} else {
// Show elevation
toolbar.setElevation(50f);
}
Asegúrese de asignar un LayoutManager
para usted RecyclerView
o la llamada de canScrollVertically ¡puede causar un accidente!
La respuesta aceptada está desactualizada. Ahora hay una funcionalidad incorporada para hacer esto. Estoy pegando todo el código de diseño para que te ayude a entenderlo.
Solo necesitas usar CoordinatorLayout
con AppBarLayout
. Este patrón de diseño se llama Levantar en desplazamiento y se puede implementar estableciendo app:liftOnScroll="true"
en tu AppBarLayout
.
Nota la liftOnScroll
El atributo requiere que aplique el @string/appbar_scrolling_view_behavior
layout_behavior a su vista de desplazamiento (p. ej., NestedScrollView
, RecyclerView
, etc.).
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
tools:context=".MainActivity"
android:background="@color/default_background">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/default_background" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/appbar"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:orientation="vertical" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Refirió esta documentación https://github.com/material-components/material-components-android/blob/master/docs/components/AppBarLayout.md
Esta es una buena pregunta, pero ninguna de las respuestas existentes es suficientemente buena. Vocación getTop()
no se recomienda en absoluto, ya que es muy poco fiable. Si observa las versiones más recientes de las aplicaciones de Google que siguen las pautas de Material Design Refresh (2018), ocultan la elevación al principio y la agregan inmediatamente cuando el usuario se desplaza hacia abajo y la ocultan nuevamente cuando el usuario se desplaza y llega a la parte superior nuevamente.
Logré lograr el mismo efecto usando lo siguiente:
val toolbar: android.support.v7.widget.Toolbar? = activity?.findViewById(R.id.toolbar);
recyclerView?.addOnScrollListener(object: RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy);
if(toolbar == null) {
return;
}
if(!recyclerView.canScrollVertically(-1)) {
// we have reached the top of the list
toolbar.elevation = 0f
} else {
// we are not at the top yet
toolbar.elevation = 50f
}
}
});
Esto funciona perfectamente con vistas de reciclador vertical (incluso con vista de pestañas u otras vistas de reciclador dentro de ellas);
Un par de notas importantes:
- Aquí estoy haciendo esto dentro de un fragmento por lo tanto
activity?.findViewById...
- Si su barra de herramientas está anidada dentro de un AppBarLayout, en lugar de aplicar elevación a la barra de herramientas, debe aplicarla a AppBarLayout.
- Deberías agregar
android:elevation="0dp"
yapp:elevation="0dp"
atributos a su barra de herramientas o AppBarLayout para que la vista del reciclador no tenga elevación al principio.