support rc01 merger library failed appcomponentfactory android android-layout material-design android-design-library collapsingtoolbarlayout

merger - implementation com android support appcompat v7 28.0 0 rc01



Barra de herramientas de colapsar animada y suave con Android Design Support Library (6)

¿Hay alguna forma de hacer que la animación de Colapsar de la Biblioteca de Soporte de Diseño de Android sea más suave mientras se desplaza? Cuando lanzo el desplazamiento, se detiene de repente. Pero lo que quiero es: la animación colapsante continuará sin problemas incluso si deja de desplazarse. Android-ObservableScrollView y Scrollable son las bibliotecas que colapsan sin problemas.


Este es bastante nuevo, pero 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"

Trataré de buscar mi fuente y actualizar mi respuesta cuando lo haga.

Editar: por supuesto, es del blog de desarrolladores de Android .


Intente agregar el siguiente código:

app:layout_scrollFlags="scroll|snap"


Lo estoy haciendo a través de AppBarLayout . anulando en onNestedFling y onNestedPreScroll .

El truco consiste en reconsumir el evento fling si el principal secundario de ScrollingView está cerca del comienzo de los datos en el Adaptador.

Fuente Flinging 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">


Puede usar la nueva distribución layout_scrollFlag para desplazamiento suave dentro de los estados de AppBarLayout. Pero lo que he experimentado es que, cuando RecyclerView llega a la cima, el desplazamiento se detiene. es decir, CollapsingToolbarLayout no se expandirá sin otro desplazamiento. Para que RecyclerView se desplace suavemente y expanda CollapsingToolbarLayout, he usado 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); } } });

Usé "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">


También estoy trabajando en este problema y he encontrado una solución no muy optimizada, pero puedes mejorarla. Una vez que la mejore, definitivamente editaré la respuesta hasta que eche 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; }

}

Crea esta clase y llama 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 se mantiene como referencia débil y GC la recopilará. Me encontré a mí mismo de una manera difícil.

Amablemente explore este código y lo mejore (cualquiera) y vuelva a compartirlo. Gracias


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 la biblioteca de soporte de diseño de Android.

<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>