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.
- ¿Cómo puedo crear un widget de interfaz de usuario de diseño de material de Android?
- Biblioteca de diálogo de material - evita el despedir / cerrar el diálogo en la función de función onPositive
- Error de la biblioteca de soporte técnico de Android 23.2.0 al establecer style = "@ style / Widget.AppCompat.Button.Colored"
- Cajón de navegación de derecha a izquierda con v7 ActionBarDrawerToggle
- Aspecto de ShareActionProvider
- Cambiar grosor de la línea inferior de EditText cuando se envuelve en TextInputLayout
- ¿Cómo implementar WhatsApp como el diseño de materiales SearchView?
- ¿Es posible alinear a la izquierda SearchView en AppCompat 21 con la barra de herramientas?
- Error al intentar probar AnimatedVectorDrawable, "No se puede cambiar de x a z"
- ¿Cómo puedo abrir mediante programación (mostrar en pantalla) NavigationView
- Cómo hacer un diseño de cuadrícula de CardViews con altura variable?
- CollapsingToolbarLayout | Problemas de desplazamiento y diseño 2
- Cómo obtener la vista de texto de la pestaña TabLayout
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"
- "MinifyEnabled" vs "shrinkResources" – ¿cuál es la diferencia? Y cómo obtener el espacio guardado?
- Manipuladores y pérdidas de memoria en Android