Barra de herramientas de colapso animado suave con Android Design Support Library

¿Hay alguna manera de hacer que la animación de Collapsing de la Biblioteca de soporte de diseño de Android sea más suave mientras se desplaza? Cuando suelto el desplazamiento, se detiene repentinamente. Pero lo que quiero es: la animación de colapso continuará sin problemas incluso si dejas de desplazarte. Android-ObservableScrollView y Scrollable son las bibliotecas que se están contrayendo sin problemas.

Puede utilizar el nuevo complemento layout_scrollFlag para desplazamiento suave dentro de los estados de AppBarLayout. Pero lo que he experimentado es que, cuando el RecyclerView alcanza la parte superior, el desplazamiento se detiene. Es decir, CollapsingToolbarLayout no se expandirá sin otro desplazamiento. Para que el RecyclerView para desplazarse sin problemas y ampliar el CollapsingToolbarLayout He utilizado un ScrollListener en recyclerview.

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { int scrollDy = 0; @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { scrollDy += dy; } @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if(scrollDy==0&&(newState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE)) { AppBarLayout appBarLayout = ((AppBarLayout) view.findViewById(R.id.app_bar)); appBarLayout.setExpanded(true); } } }); 

Utilicé "scroll | exitUntilCollapsed" como layout_scrollFlags.

 <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:minHeight="80dp" app:layout_collapseMode="none" app:layout_scrollFlags="scroll|exitUntilCollapsed"> 

Este es bastante nuevo, pero el AppBarLayout se ha actualizado recientemente para manejar exactamente lo que estás buscando con un nuevo layout_scrollFlag llamado snap .

Uso:

 app:layout_scrollFlags="scroll|snap" 

Voy a tratar de buscar mi fuente y actualizar mi respuesta cuando lo hago.

Edit: Por supuesto, es del blog desarrollador android .

Lo estoy haciendo a través de AppBarLayout . Por sobreescribir onNestedFling y onNestedPreScroll .

El truco consiste en reconstruir el evento fling si el hijo superior de ScrollingView está cerca del inicio de los datos en Adapter.

Flinging de la fuente con RecyclerView + AppBarLayout

 public final class FlingBehavior extends AppBarLayout.Behavior { private static final int TOP_CHILD_FLING_THRESHOLD = 3; private boolean isPositive; public FlingBehavior() { } public FlingBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) { if (velocityY > 0 && !isPositive || velocityY < 0 && isPositive) { velocityY = velocityY * -1; } if (target instanceof RecyclerView && velocityY < 0) { final RecyclerView recyclerView = (RecyclerView) target; final View firstChild = recyclerView.getChildAt(0); final int childAdapterPosition = recyclerView.getChildAdapterPosition(firstChild); consumed = childAdapterPosition > TOP_CHILD_FLING_THRESHOLD; } return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed); } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed) { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); isPositive = dy > 0; } } 

A continuación, establezca el comportamiento de diseño como clase FlingBehavior

 <android.support.design.widget.AppBarLayout app:layout_behavior="package.FlingBehavior" android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="250dip" android:fitsSystemWindows="true"> 

Agregar código

  app:layout_scrollFlags="scroll|enterAlways" 

En la vista dentro de AppBarLayout. Este es mi código de demostración que colapsa la barra de herramientas con Android Design Support Library.

  <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_scrollFlags="scroll|enterAlways"> <bubee.inews.Items.ItemMenu android:id="@+id/itemMenu" android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> 

Estoy trabajando en este problema también y han surgido con la solución no puede muy optimizado, pero se puede mejorar. Una vez que mejorarlo definitivamente voy a editar la respuesta hasta el echar un vistazo a esto.

 public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener { private static final String TAG = "app_AppBarStateChange"; public enum State { EXPANDED, COLLAPSED, IDLE } private State mCurrentState = State.IDLE; private int mInitialPosition = 0; private boolean mWasExpanded; private boolean isAnimating; @Override public final void onOffsetChanged(AppBarLayout appBarLayout, int i) { if (i == 0) { if (mCurrentState != State.EXPANDED) { onStateChanged(appBarLayout, State.EXPANDED); } mCurrentState = State.EXPANDED; mInitialPosition = 0; mWasExpanded = true; Log.d(TAG, "onOffsetChanged 1"); isAnimating = false; appBarLayout.setEnabled(true); } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) { if (mCurrentState != State.COLLAPSED) { onStateChanged(appBarLayout, State.COLLAPSED); } mCurrentState = State.COLLAPSED; mInitialPosition = appBarLayout.getTotalScrollRange(); mWasExpanded = false; Log.d(TAG, "onOffsetChanged 2"); isAnimating = false; appBarLayout.setEnabled(true); } else { Log.d(TAG, "onOffsetChanged 3"); int diff = Math.abs(Math.abs(i) - mInitialPosition); if(diff >= appBarLayout.getTotalScrollRange()/3 && !isAnimating) { Log.d(TAG, "onOffsetChanged 4"); isAnimating = true; appBarLayout.setEnabled(false); appBarLayout.setExpanded(!mWasExpanded,true); } if (mCurrentState != State.IDLE) { onStateChanged(appBarLayout, State.IDLE); } mCurrentState = State.IDLE; } } public abstract void onStateChanged(AppBarLayout appBarLayout, State state); public State getCurrentState() { return mCurrentState; } 

}

Cree esta clase y llame al siguiente código

 private AppBarStateChangeListener mAppBarStateChangeListener = new AppBarStateChangeListener() { @Override public void onStateChanged(AppBarLayout appBarLayout, State state) { Log.d(TAG, "ToBeDeletedActivity.onStateChanged :: " + state); if(state == State.EXPANDED || state == State.IDLE) { getSupportActionBar().setTitle(""); } else { getSupportActionBar().setTitle("Hello World"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mAppBarLayout.setElevation(0); } } } }; mAppBarLayout.addOnOffsetChangedListener(mAppBarStateChangeListener); 

Tenga en cuenta que no establezca la clase anónima OffsetChangedListener ya que esto se mantiene como referencia débil y será recogido por GC.I encontró mi auto de manera dura.

Amablemente explorar este código y mejorarlo (cualquier persona) y volver a compartirlo. Gracias

Intente agregar el siguiente código:

  app:layout_scrollFlags="scroll|snap" 
  • Cómo deshabilitar flotante mientras muestra error en TextInputLayout
  • Cambiar el tema de diseño predeterminado a color personalizado?
  • Diseño de material - Barra de herramientas de AppCompat sin mostrar sombra
  • ¿Cómo diseñar el NavigationView de la biblioteca de soporte de diseño?
  • Superposición de contenido por encima de AppBarLayout utilizando nuevo diseño de material
  • Snackbar oculta la acción flotante al presionar el botón de acción en ella
  • Cómo establecer el comportamiento de comprobación compartida en todos los grupos en NavigationView?
  • Botones planos sin material Lollipop
  • ¿Dónde puedo encontrar y descargar iconos de diseño de material para mi aplicación para Android?
  • Botón desplegable de Android
  • Uso correcto de un Spinner, siguiendo las directrices de diseño del material
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.