Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Smooth animated Collapsing Toolbar with Android Design Support Library

Are there anyway to make Android Design Support Library's Collapsing animation smoother while scrolling? When I release scrolling, it stops suddenly. But what I want is: collapsing animation will continue smoothly even if you stop scrolling. Android-ObservableScrollView and Scrollable are the libraries that are collapsing smoothly.

like image 773
metemet06 Avatar asked Jul 06 '15 01:07

metemet06


3 Answers

You can use the new layout_scrollFlag snap for smooth scroll within the AppBarLayout states. But what I have experienced is that, when the RecyclerView reaches top, scrolling stops. i.e CollapsingToolbarLayout won't get expanded without another scroll. For the RecyclerView to scroll smoothly up and expand the CollapsingToolbarLayout I have used a ScrollListener on 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);
            }
        }
    });

I used "scroll|exitUntilCollapsed" as 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">
like image 95
Jossy Paul Avatar answered Oct 24 '22 07:10

Jossy Paul


This one is fairly new, but the AppBarLayout has been recently updated to handle exactly what you're looking for with a new layout_scrollFlag called snap.

Usage:

app:layout_scrollFlags="scroll|snap"

I'll try to look for my source and update my answer when I do.

Edit: Of course, it's from the android developer blog.

like image 7
josephus Avatar answered Oct 24 '22 08:10

josephus


I'm doing it through AppBarLayout. by overriding onNestedFling and onNestedPreScroll.

The trick is to reconsume fling event if ScrollingView's top child is close to the beginning of data in Adapter.

Source Flinging with 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;
  }
}

Then set the layout behavior as FlingBehavior class

<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">
like image 3
S.R Avatar answered Oct 24 '22 08:10

S.R