android - tutorial - ¿Cómo deshabilitar el desplazamiento de AppBarLayout en CoordinatorLayout?
coordinatorlayout collapse (5)
Entonces, después de dos horas de intentarlo, he encontrado una solución, que es bastante simple. Solo necesitaba extender CoordinatorLayout
y anular el método OnInterceptTouchEvent
para que la clase se vea así:
public class NonTouchableCoordinatorLayout extends CoordinatorLayout {
public NonTouchableCoordinatorLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
}
Tengo MapFragment
con efecto de paralaje dentro de AppBarLayout
:
Quiero deshabilitar el desplazamiento en AppBarLayout
, ya que no es posible desplazarse por el mapa, ya que las teclas de toque en el mapa siempre se manejan como eventos de desplazamiento. Me gustaría manejar el colapso de AppBarLayout
desplazando RecyclerView
solamente, que se encuentra en la parte inferior de la pantalla.
Este es mi xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:contentScrim="@color/white"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:titleEnabled="false">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_collapseMode="parallax"
android:fitsSystemWindows="true">
<fragment
android:id="@+id/map"
android:name="com.androidmapsextensions.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="73dp"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<include
android:id="@+id/search_bar"
layout="@layout/layout_searchbar" />
</android.support.v7.widget.Toolbar>
<View
android:id="@+id/toolbar_shadow"
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_below="@id/search_bar"
android:layout_gravity="bottom"
android:background="@drawable/toolbar_dropshadow"
android:visibility="gone" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<RecyclerView
android:id="@+id/farm_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
Gracias por la respuesta.
No estoy seguro de haberlo conseguido, pero creo que estás buscando un DragCallback
.
La interfaz DragCallback
permite elegir si la vista de desplazamiento de hermanos debe controlarse mediante los desplazamientos en AppBarLayout
.
Puedes definir uno llamando al:
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
@Override
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
return false;
}
});
Al devolver siempre false
, su vista de desplazamiento ya no será controlada por la ABL.
Nota: antes de llamar a esto, debe verificar que ViewCompat.isLaidOut(appBarLayout)
, de lo contrario params.getBehavior()
devolverá nulo.
Puedes lograr esto definiendo una app:layout_behavior
personalizada app:layout_behavior
en xml. Con este enfoque, no tiene que preocuparse por obtener una referencia a los LayoutParams
y realizar comprobaciones nulas.
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.yourcompany.FixedAppBarLayoutBehavior"
>
Luego cree una clase personalizada que se extienda desde AppBarLayout.Behavior
.
public class FixedAppBarLayoutBehavior extends AppBarLayout.Behavior {
public FixedAppBarLayoutBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
setDragCallback(new DragCallback() {
@Override public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
return false;
}
});
}
}
Actualizado con la versión Kotlin:
class FixedAppBarLayoutBehavior(context: Context, attrs: AttributeSet) : AppBarLayout.Behavior(context, attrs) {
init {
setDragCallback(object : DragCallback() {
override fun canDrag(appBarLayout: AppBarLayout): Boolean = false
})
}
}
puede usar el NestedScrollView.setNestedScrollingEnabled(false)
para deshabilitar el entorno de anidación de la aplicación AppBarLayout
Problema
- AppBarLayout se desplaza incluso si el contenido de desplazamiento se ajusta a la pantalla.
- Esto se debe a que, de forma predeterminada, podemos arrastrar AppBarLayout tocando y arrastrando AppBarLayout.
Solución
Deshabilitaremos el comportamiento de "Arrastrar" para AppBarLayout.
// Disable "Drag" for AppBarLayout (i.e. User can''t scroll appBarLayout by directly touching appBarLayout - User can only scroll appBarLayout by only using scrollContent) if (appBarLayout.getLayoutParams() != null) { CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); AppBarLayout.Behavior appBarLayoutBehaviour = new AppBarLayout.Behavior(); appBarLayoutBehaviour.setDragCallback(new AppBarLayout.Behavior.DragCallback() { @Override public boolean canDrag(@NonNull AppBarLayout appBarLayout) { return false; } }); layoutParams.setBehavior(appBarLayoutBehaviour); }
Referencia
Esta es solo una extensión de la respuesta aceptada de "natario" arriba.