最近在研究CoordinatorLayout和Behavior的相关特性,在泡网看到Behavior实现的简书快速返回效果 ,觉得实现相对简单,突然灵机一动,想到用Behavior来做RecyclerView的粘性头部,通过不断尝试发现Behavior中获得的滑动距离不大准确,并不是我想要的。于是果断放弃此路,通过监听RecyclerView的滑动来实现。
效果图
实现思路 1.布局结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:app ="http://schemas.android.com/apk/res-auto" android:layout_width ="match_parent" android:layout_height ="match_parent" > <android.support.design.widget.AppBarLayout android:id ="@+id/appbar" android:layout_width ="match_parent" android:layout_height ="wrap_content" > <android.support.v7.widget.Toolbar android:layout_width ="match_parent" android:layout_height ="wrap_content" android:theme ="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:navigationIcon ="?attr/homeAsUpIndicator" app:title ="title" /> </android.support.design.widget.AppBarLayout > <android.support.v7.widget.RecyclerView android:id ="@+id/rv_behavior" android:layout_width ="match_parent" android:layout_height ="match_parent" android:background ="#f2f2f2" app:layout_behavior ="@string/appbar_scrolling_view_behavior" /> <TextView android:id ="@+id/sticky_header" android:layout_width ="match_parent" android:layout_height ="wrap_content" android:padding ="20dp" android:background ="#e89112" android:gravity ="center" android:text ="sticky header" android:textColor ="@android:color/white" /> </android.support.design.widget.CoordinatorLayout >
RecyclerView普通header
1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:orientation ="vertical" android:layout_width ="match_parent" android:layout_height ="wrap_content" > <ImageView android:layout_width ="match_parent" android:layout_height ="200dp" android:src ="@mipmap/girl" android:scaleType ="centerCrop" /> </LinearLayout >
RecyclerView sticky header
1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:orientation ="vertical" android:layout_width ="match_parent" android:layout_height ="wrap_content" > <TextView android:layout_width ="match_parent" android:layout_height ="wrap_content" android:padding ="20dp" /> </LinearLayout >
RecyclerView item
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:orientation ="vertical" android:layout_width ="match_parent" android:layout_height ="wrap_content" > <TextView android:layout_marginBottom ="1dp" android:id ="@+id/tv_content" android:layout_width ="match_parent" android:layout_height ="wrap_content" android:padding ="10dp" android:background ="@android:color/white" /> </LinearLayout >
ps:RecyclerView中包括三部分,普通header、sticky header、item;其中sticky header是假view,只是为了占个高度。 真正的sticky header在CoordinatorLayout中。
2.滑动处理 主要就是添加滑动监听,把RecyclerView滑动距离算出来,然后与最大滑动距离比较,即普通header的高度,如果差值>0,则滑动此距离,<0就不滑动。这样就可以把某个header定在一处。
主要代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 maxDist=ScreenUtils.dip2px(this ,200 ); stickyView=findViewById(R.id.sticky_header); recyclerView= (RecyclerView) findViewById(R.id.rv_behavior); initData(); recyclerView.setLayoutManager(new LinearLayoutManager(this )); recyclerView.setAdapter(new StickyHeaderAdapter(this ,data)); appbar= (AppBarLayout) findViewById(R.id.appbar); appbar.post(new Runnable() { @Override public void run () { barHeight= appbar.getMeasuredHeight(); stickyView.setTranslationY(maxDist+barHeight); } }); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged (RecyclerView recyclerView, int newState) { super .onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled (RecyclerView recyclerView, int dx, int dy) { totalChange+=dy; Log.e(TAG,"totalChange:" +totalChange); int tranY=Math.max(0 ,maxDist-totalChange); stickyView.setTranslationY(tranY+barHeight); } });
总结 其实实现过程还是蛮容易的,但还存在一些问题,比如要实现多个sticky header就比较困难。FlexibleAdapter 这个开源项目就考虑得很全面,很多功能都有。下一篇博文将介绍此文章的姊妹篇,ScrollView实现粘性头部,敬请期待!
参考资料
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0224/3991.html
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0913/3447.html