sheet medium from example bottomsheetbehavior bottom behaviour android android-support-library ontouchlistener ontouchevent touch-event android-support-design

android - medium - Uso de BottomSheetBehavior con un CoordinatorLayout interno



bottom sheet behaviour android (6)

Acabo de seguir la forma en que hizo la pregunta anterior y encontré una solución que podría necesitar más explicación. Siga su código de muestra e integre la parte adicional en su xml para que se comporte como el comportamiento de BottomSheeet

<CoordinatorLayout> <AppBarLayout> <Toolbar app:layout_collapseMode="pin"> </Toolbar> </AppBarLayout> <NestedScrollView app:layout_behavior=“@string/bottom_sheet_behavior” > <include layout="@layout/items" /> </NestedScrollView> <!-- Bottom Sheet --> <BottomSheetCoordinatorLayout> <AppBarLayout <CollapsingToolbarLayout"> <ImageView /> <Toolbar /> </CollapsingToolbarLayout> </AppBarLayout> <NestedScrollView"> <include layout="@layout/items" /> </NestedScrollView> </BottomSheetCoordinatorLayout> </CoordinatorLayout>

Nota: La solución que funcionó para mí ya se explicó en el último comentario de su pregunta

Mejor explicación: https://github.com/laenger/BottomSheetCoordinatorLayout

La biblioteca de soporte de diseño v. 23.2 introdujo BottomSheetBehavior , que permite que los hijos de un coordinador actúen como hojas inferiores (vistas arrastrables desde la parte inferior de la pantalla).

Lo que me gustaría hacer es tener, como una vista de la hoja inferior , la siguiente vista (el coordinador típico + cosas colapsadas):

<CoordinatorLayout app:layout_behavior=“@string/bottom_sheet_behavior”> <AppBarLayout> <CollapsingToolbarLayout> <ImageView /> </CollapsingToolbarLayout> </AppBarLayout> <NestedScrollView> <LinearLayout> < Content ... /> </LinearLayout> </NestedScrollView> </CoordinatorLayout>

Desafortunadamente, las vistas de la hoja inferior deberían implementar un desplazamiento anidado, o no obtendrán eventos de desplazamiento. Si intenta con una actividad principal y luego carga esta vista como una hoja inferior, verá que los eventos de desplazamiento solo actúan en la "hoja" de papel, con un comportamiento extraño, como puede ver si sigue leyendo.

Estoy bastante seguro de que esto se puede manejar subclasificando CoordinatorLayout , o incluso mejor subclasificando BottomSheetBehavior . ¿Tienes alguna pista?

Algunos pensamientos

  • Se debe usar requestDisallowInterceptTouchEvent() , para robar eventos del padre en algunas condiciones:

    • cuando el desplazamiento de AppBarLayout es> 0
    • cuando el desplazamiento de AppBarLayout es == 0, pero estamos desplazándonos hacia arriba ( AppBarLayout por un segundo y verá)
  • la primera condición se puede obtener estableciendo un OnOffsetChanged en la barra de aplicaciones interna;

  • el segundo requiere algún manejo de eventos, por ejemplo:

    switch (MotionEventCompat.getActionMasked(event)) { case MotionEvent.ACTION_DOWN: startY = event.getY(); lastY = startY; userIsScrollingUp = false; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: userIsScrollingUp = false; break; case MotionEvent.ACTION_MOVE: lastY = event.getY(); float yDeltaTotal = startY - lastY; if (yDeltaTotal > touchSlop) { // Moving the finger up. userIsScrollingUp = true; } break; }

Cuestiones

No hace falta decir que no puedo hacer que esto funcione en este momento. No puedo atrapar los eventos cuando se cumplen las condiciones, y no atraparlos en otros casos. En la imagen a continuación, puede ver lo que sucede con un CoordinatorLayout estándar:

  • La hoja se descarta si se desplaza hacia abajo en la barra de aplicaciones, pero no si se desplaza hacia abajo en el contenido anidado. Parece que los eventos de desplazamiento anidados no se propagan al comportamiento del Coordinador;

  • También hay un problema con la barra de aplicaciones interna: el contenido de desplazamiento anidado no sigue a la barra de aplicaciones cuando se contrae.

He configurado un proyecto de muestra en github que muestra estos problemas.

Para ser claros, el comportamiento deseado es:

  • Comportamiento correcto de las barras de aplicaciones / vistas de desplazamiento dentro de la hoja;

  • Cuando la hoja se expande, puede colapsar al desplazarse hacia abajo, pero solo si la barra de aplicaciones interna también se expande completamente . En este momento, colapsa sin tener en cuenta el estado de la barra de aplicaciones, y solo si arrastra la barra de aplicaciones;

  • Cuando la hoja se contrae, los gestos de desplazamiento hacia arriba la expandirán (sin efecto en la barra de aplicaciones interna).

Un ejemplo de la aplicación de contactos (que probablemente no usa BottomSheetBehavior, pero esto es lo que quiero):


El diseño para la pantalla completa del diseño de la barra de aplicaciones es el siguiente:

<android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="@dimen/detail_backdrop_height" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:fitsSystemWindows="true"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed" android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginStart="48dp" app:expandedTitleMarginEnd="64dp"> <ImageView android:id="@+id/backdrop" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:fitsSystemWindows="true" app:layout_collapseMode="parallax" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_collapseMode="pin" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingTop="24dp"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/card_margin"> <LinearLayout style="@style/Widget.CardContent" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Info" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheese_ipsum" /> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/card_margin" android:layout_marginLeft="@dimen/card_margin" android:layout_marginRight="@dimen/card_margin"> <LinearLayout style="@style/Widget.CardContent" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Friends" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheese_ipsum" /> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/card_margin" android:layout_marginLeft="@dimen/card_margin" android:layout_marginRight="@dimen/card_margin"> <LinearLayout style="@style/Widget.CardContent" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Related" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheese_ipsum" /> </LinearLayout> </android.support.v7.widget.CardView> </LinearLayout> </android.support.v4.widget.NestedScrollView> <android.support.design.widget.FloatingActionButton android:layout_height="wrap_content" android:layout_width="wrap_content" app:layout_anchor="@id/appbar" app:layout_anchorGravity="bottom|right|end" android:src="@drawable/ic_discuss" android:layout_margin="@dimen/fab_margin" android:clickable="true"/>

y después de eso, debe implementar AppBarLayout.OnOffsetChangedListener en su clase y establecer el desplazamiento de la pantalla.


Finalmente he lanzado mi implementación. Encuéntralo en Github o directamente desde jcenter:

compile ''com.otaliastudios:bottomsheetcoordinatorlayout:1.0.0’

Todo lo que tiene que hacer es usar BottomSheetCoordinatorLayout como la vista raíz de su hoja inferior. Inflará automáticamente un comportamiento de trabajo por sí mismo, así que no te preocupes por eso.

He estado usando esto durante mucho tiempo y no debería tener problemas de desplazamiento, admite arrastrar el ABL, etc.


He seguido el proyecto inicial de prueba de github de laenger con respecto a este problema, y ​​me complace compartir una solución para algunos de sus problemas, ya que también necesitaba este comportamiento en mi aplicación.

esta es una solución a su problema: ❌ la barra de herramientas a veces se colapsa demasiado pronto

para evitar esto, debe crear su AppBarLayout.Behavior personalizado, ya que es cuando se desplaza hacia arriba mientras sigue arrastrando que AppBarLayout.behavior obtiene el movimiento de desplazamiento. Necesitamos detectar si está en STATE_DRAGGING y regresar para evitar ocultar / colapsar la barra de herramientas prematuramente.

public class CustomAppBarLayoutBehavior extends AppBarLayout.Behavior { private CoordinatorLayoutBottomSheetBehavior behavior; public CustomAppBarLayoutBehavior() { } public CustomAppBarLayoutBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) { behavior = CoordinatorLayoutBottomSheetBehavior.from(parent); return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes); } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed) { if(behavior.getState() == CoordinatorLayoutBottomSheetBehavior.STATE_DRAGGING){ return; }else { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); } } @Override public void setDragCallback(@Nullable DragCallback callback) { super.setDragCallback(callback); } }

Este puede ser un buen comienzo para resolver los otros problemas:

❌ barra de herramientas no se puede contraer a través de arrastrar

Layout El diseño del coordinador principal consume algo de desplazamiento

en realidad no soy una buena persona de UI / animación, pero el trabajo duro a veces vale la pena entender el código, encontrando la función correcta de devolución de llamada / anulación para implementar.

configura esto como comportamiento para appbarlayout

<android.support.design.widget.AppBarLayout android:id="@+id/bottom_sheet_appbar" style="@style/BottomSheetAppBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_behavior="your.package.CustomAppBarLayoutBehavior">


Intente no usar NestedScrollView con LinearLayout , también ha estado causando problemas en mi aplicación. Solo use LinearLayout en LinearLayout lugar, funciona bien para mí.

Intenta lo siguiente:

<CoordinatorLayout app:layout_behavior=“@string/bottom_sheet_behavior”> <AppBarLayout> <CollapsingToolbarLayout> <ImageView /> </CollapsingToolbarLayout> </AppBarLayout> <LinearLayout> <!--don''t forget to addd this line--> app:layout_behavior="@string/appbar_scrolling_view_behavior"> < Content ... /> </LinearLayout>


Si el primer hijo está nestedscroll esto ocurrirá con otros problemas. Esta solución solucionó mi problema, espero que también solucione el suyo.

<CoordinatorLayout app:layout_behavior=“@string/bottom_sheet_behavior”> <AppBarLayout> <CollapsingToolbarLayout> <ImageView /> </CollapsingToolbarLayout> </AppBarLayout> </LinearLayout> <NestedScrollView> <LinearLayout> < Content ... /> </LinearLayout> </NestedScrollView> </LinearLayout> </CoordinatorLayout>