Y a-t-il une façon de rendre plus fluide Android Design Support Library de l'effacement de l'animation pendant le défilement? Lorsque je relâche le défilement, il s'arrête soudainement. Android-ObservableScrollView et Scrollable sont les bibliothèques qui s'effondrent en douceur.
Vous pouvez utiliser le nouvel instantané layout_scrollFlag pour un défilement fluide dans les états AppBarLayout. Mais ce que j'ai vécu, c'est que lorsque le RecyclerView atteint le sommet, le défilement s'arrête. i.e CollapsingToolbarLayout ne sera pas développé sans un autre défilement. Pour que RecyclerView défile en douceur et développe le CollapsingToolbarLayout, j'ai utilisé un ScrollListener sur 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);
}
}
});
J'ai utilisé "scroll | exitUntilCollapsed" comme 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">
Celui-ci est assez nouveau, mais l'AppBarLayout a été récemment mis à jour pour gérer exactement ce que vous recherchez avec un nouveau layout_scrollFlag appelé snap
.
Usage:
app:layout_scrollFlags="scroll|snap"
Je vais essayer de chercher ma source et mettre à jour ma réponse quand je le ferai.
Edit: Bien sûr, cela vient du blog des développeurs Android .
Je le fais via AppBarLayout
. en remplaçant onNestedFling
et onNestedPreScroll
.
L'astuce consiste à reconsommer l'événement fling si l'enfant supérieur de ScrollingView est proche du début des données dans l'adaptateur.
Source Flinging avec 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;
}
}
Définissez ensuite le comportement de disposition en tant que classe 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">
ajouter du code
app:layout_scrollFlags="scroll|enterAlways"
dans la vue à l'intérieur de l'AppBarLayout. Ceci est mon code de démonstration réduisant la barre d'outils avec 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>
Je travaille aussi sur ce problème et j'ai trouvé une solution peut-être pas très optimisée mais vous pouvez l'améliorer.
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;
}
}
Créez cette classe et appelez le code suivant
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);
Notez que ne définissez pas la classe annonymous OffsetChangedListener car cela est conservé comme référence faible et sera collecté par GC.J'ai trouvé mon auto de manière difficile.
Veuillez explorer ce code et l'améliorer (n'importe qui) et le partager à nouveau.
Essayez d'ajouter le code suivant:
app:layout_scrollFlags="scroll|snap"