前言:因为项目中有个界面使用到父view和子view嵌套滑动的效果,所以想使用CoordinatorLayout来实现。在这当中遇到一些坑,本文作为一个记录。
现在用的UI库版本:
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support:support-v4:24.2.1'
compile 'com.android.support:design:24.2.1'
ps:因为我现在遇到的坑可能在之后的版本会修复,所以就先版本写这。
刚开始的实现想法是,整个结构是CoordinatorLayout,包含一个AppbarLayout作为头部View,下面是一个ViewPager指示器,再下面是一个ViewPager。
最终效果:
主页布局代码:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.oacg.collapsingtoolbarlayoutdemo.CoorAndViewPagerActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/profile_app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/profile_collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="280dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:contentScrim="?attr/colorPrimary"
android:fitsSystemWindows="true">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="280dp"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
android:src="@drawable/bg"
android:maxHeight="192dp"
app:layout_collapseMode="parallax"/>
android.support.design.widget.CollapsingToolbarLayout>
<com.oacg.collapsingtoolbarlayoutdemo.SimpleViewPagerIndicator
android:id="@+id/indicator"
android:layout_width="match_parent"
android:layout_height="50dp"/>
android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
android.support.design.widget.CoordinatorLayout>
出现的问题:
在滚动的时候出现一种卡顿的现象。主要是在NestedScrollView向上滚动和RecyclerView向下滚动的时候。AppbarLayout的滚动非常的不流畅。感觉上是没有了惯性滑动。
解决办法:
这里可以看到 为了头部View滚动优先于ViewPager,所以我在给CollapsingToolbarLayout设置app:layout_scrollFlags
的时候我使用的是:scroll|exitUntilCollapsed
。加入ViewPager中的NestedScrollView和RecyclerView比较短的时候,可以考虑使用 scroll|exitUntilCollapsed|enterAlways
。
上面的解决方式显然是有很大的局限性。那么第二种解决方式。
即:
http://stackoverflow.com/questions/30923889/flinging-with-recyclerview-appbarlayout 第一个答案。用于解决RecyclerView的问题。
出现这种问题的原因大体上是因为RecyclerView在分发fling的时候出现了错误,导致AppbarLayout并没有获得fling的指令。所以这个方法,就自己重新计算了时候需要fling的判断。
但是这个方法还是没法解决NestedScrollView的滑动卡顿问题。虽然上面链接的第二个答案,看上去能解决NestedScrollView的滑动卡顿问题,但是并没有卵用。这个之后再说。
上面的解决办法,大多是对于RecyclerView的对于NestedScrollView是无效的。因为在NestedScrollView根本就没有把fling正确的发出来。NestedScrollView的onTouchEvent()方法中:
case MotionEvent.ACTION_UP:
if (mIsBeingDragged) {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.addMovement(vtev);
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int initialVelocity = (int) VelocityTrackerCompat.getYVelocity(velocityTracker,
mActivePointerId);
if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
flingWithNestedDispatch(-initialVelocity);
} else if (mScroller.springBack(getScrollX(), getScrollY(), 0, 0, 0,
getScrollRange())) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
mActivePointerId = INVALID_POINTER;
endDrag();
break;
触发up事件的时候会来处理fling事件。flingWithNestedDispatch(-initialVelocity)
用来发送fling事件和处理fling事件。出现卡顿的时候就是if (mIsBeingDragged)
这个判断为false的时候。
那么解决NestedScrollView滚动卡顿的办法就是:自己新建一个类,然后将NestedScrollView中的代码copy到新的类中,并在onTouchEvent()方法的case MotionEvent.ACTION_UP:
中去掉if (mIsBeingDragged)
判断,然后就可以流畅的滑动了。至于这个判断去掉会不会有什么其他问题,暂时我还没发现,如果您知道请务必告诉我。谢谢。
总结:CoordinatorLayout上的这个卡顿的问题,官方早就知道这个问题,官方说是v23就修复的,
现在v24了也没有变化。可以看这里的讨论。https://code.google.com/p/android/issues/detail?id=179501
As I said in the talk, no there is ETA and may not even land. Closing comments until we do. 看到这句话一口老血吐出来。
所以在stackoverflow.com有很多的讨论,而且也有很多的解决办法,我感觉能达到的效果的都是有限的。不能真正的解决问题。
ps:https://github.com/henrytao-me/smooth-app-bar-layout 这个库是实现类似效果的,具体的效果怎么我没有去试。
pps: coordinatorlayout在android6.0的华为的机子上测试的时候快速滑动RecyclerView,会出现跳动的问题,暂时还不知道是因为我设置的问题还是因为coordinatorlayout的bug。
源码地址:https://github.com/BigggFish/CoordinatorlayoutDemo
参考:
http://dk-exp.com/2016/03/30/CoordinatorLayout/
http://stackoverflow.com/questions/30923889/flinging-with-recyclerview-appbarlayout
http://stackoverflow.com/questions/38119661/smooth-scroll-and-fling-with-nestedscrollview-appbarlayout-and-coordinatorlayout?rq=1