本文主要是介绍RecyclerView自定义LayoutManager实现横向瀑布流,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
最近由于公司项目需要,做了一个横向瀑布流的组件,如下图;这个组件是通过自定义LayoutManager实现,LayoutManager为我们提供了强大的自定义功能,但是实现过程却不简单,捣鼓了两天,也就算基本可以用了;Demo源码在最下面,这里主要记录一些自定义LayoutManager过程中需要注意的细节和关键点;
(这个Demo以及下面的记录参考文章:http://blog.csdn.net/zxt0601/article/details/52948009)
一 关键重写方法:
1、generateDefaultLayoutParams();
如果没有特殊需求,大部分情况下,我们只需要如下重写该方法即可。
- 1
- 2
- 3
- 4
该方法是LayoutManager的入口。它会在如下情况下被调用:
1 在RecyclerView初始化时,会被调用两次。
2 在调用adapter.notifyDataSetChanged()时,会被调用。
3 在调用setAdapter替换Adapter时,会被调用。
4 在RecyclerView执行动画时,它也会被调用。
即RecyclerView 初始化 、 数据源改变时 都会被调用。
它相当于ViewGroup的onLayout()方法,所以我们需要在里面layout当前屏幕可见的所有子View,千万不要layout出所有的子View。如果在这里绘制所有的子View,那么在我们每次调用NotifyDataSetChanged方法时,就会重新绘制所有的子View,如果有一万条数据,那么将会等待5S左右的时间,ANR!
3、竖直滚动需要 重写canScrollVertically()和scrollVerticallyBy()
@Overridepublic boolean canScrollVertically() {return true;}
在canScrollVertically()方法中,我们要实现滚动、重绘、子View回收和重用,控制滚动速度;
滚动和重绘:
滚动时需要注意边界判断;
子View 的回收和重用:
一个View只是暂时被清除掉,稍后立刻就要用到,使用detach。它会被缓存进scrapCache的区域。
一个View 不再显示在屏幕上,需要被清除掉,并且下次再显示它的时机目前未知 ,使用remove。它会被以viewType分组,缓存进RecyclerViewPool里。
注意:一个View只被detach,没有被recycle的话,不会放进RecyclerViewPool里,会一直存在recycler的scrap 中。
这里引出一个平时没有关注细节,即RecyclerView.Adapter的getItemViewType()方法;如果重写这个方法如下的话:
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
这样每一个ItemViewType都不一样,RecyclerView不会有任何的复用,因为每一个ItemView在RecyclerViewPool里都找不到可以复用的holder,ItemView有n个,onCreateViewHolder方法会执行n次。
控制滚动速度:
该方法return的值如果和传进来的dy值不同,RecyclerView就会认为到达边界,就会停止fling并显示边界光晕;
经测试该return值只用来判断边界,没有其他作用;
所以我们就可以在此处修改滑动速度,在未到达边界时返回dy,这样就不会让RecyclerView误认为已到达边界了;
二 常用API:
布局API:
- 1
- 2
- 3
- 1
- 2
- 3
- 1
- 2
- 1
- 2
- 1
- 1
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
回收API:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 1
- 2
- 3
移动子ViewAPI:
- 1
- 2
- 1
- 2
工具API:
- 1
- 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
三 Demo的说明:
实现功能:实现横向流式布局,实现了子View 的回收和重用,实现了SmoothScrollToPosition功能,实现了NotifyDataSetChanged方法更新数据的功能;
存在缺陷:如果更换数据(特指某Position上的子View的大小可能改变),需要给RecyclerView重新new一个LayoutManager,否则显示会有问题;
未实现ScrollToPosition功能;未实现定向更新功能;
注:有关于该组件在首次非常快速滑动时,可能出现子View位置计算错误的问题(推测应该是滑动过快,而计算并未能实时完成,最终造成位置计算错误),已通过控制滑动速度和fling速度解决;
Demo下载地址;
这篇关于RecyclerView自定义LayoutManager实现横向瀑布流的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!