我们知道,Desgin包中的AppBarLayout配合CollapsingToolbarLayout可以实现折叠效果。但是顶部在快速滑动到折叠状态时,底部的NestedScrollChild不会因为惯性跟着滑动,整个滑动过程瞬间停止,给人一种很不流畅的感觉。为了能让我们的AppBarLayout能Fling更流畅,我们需要在重新修改源码,定制一个FlingAppBarLayout,能够实现类似饿了么首页效果
思路
我们知道AppBarLayout之所以能够有折叠效果,是因为有一个默认的Behavior,而且AppBarLayout在快速滑动时,布局也能够快速展开和收缩,因此可以猜测内部有可能处理了Fling事件。通过源码,找到对应的Behavior,它继承自HeaderBehavior,通过onTouchEvent方法,找到了对应对于Fling事件的处理 case MotionEvent.ACTION_UP: if (mVelocityTracker != null) {
mVelocityTracker.addMovement(ev); mVelocityTracker.computeCurrentVelocity(1000); float yvel = mVelocityTracker.getYVelocity(mActivePointerId); fling(parent, child, -getScrollRangeForDragFling(child), 0, yvel); }
进入fling方法,找到了scroller对象,AppBarLayout的快速滑动效果就是通过它来实现的。至于为什么AppBarLayout向上快速滑动到边界时,突然停止,没有惯性滑动,是因为scroller在调用fling方法时设置了minOffset(向上滑动边界)
final boolean fling(CoordinatorLayout coordinatorLayout, V layout, int minOffset, int maxOffset, float velocityY) {
if (mFlingRunnable != null) {
layout.removeCallbacks(mFlingRunnable); mFlingRunnable = null; } if (mScroller == null) {
mScroller = new OverScroller(layout.getContext()); } mScroller.fling( 0, getTopAndBottomOffset(), // curr 0, Math.round(velocityY), // velocity. 0, 0, // x minOffset, maxOffset); // y if (mScroller.computeScrollOffset()) {
mFlingRunnable = new FlingRunnable(coordinatorLayout, layout); ViewCompat.postOnAnimation(layout, mFlingRunnable); return true; } else {
onFlingFinished(coordinatorLayout, layout); return false; } }
而具体的view的移动,则是通过FlingRunnable来实现。
private class FlingRunnable implements Runnable {
private final CoordinatorLayout mParent; private final V mLayout; FlingRunnable(CoordinatorLayout parent, V layout) {
mParent = parent; mLayout = layout; } @Override public void run() {
if (m