ItemDecoration实现固定悬浮式Item的思路
来源:互联网 发布:魔兽世界mac版 编辑:程序博客网 时间:2024/04/30 18:31
转载请注意:http://blog.csdn.net/wjzj000/article/details/78177509
本菜开源的一个自己写的Demo,希望能给Androider们有所帮助,水平有限,见谅见谅…
https://github.com/zhiaixinyang/PersonalCollect (拆解GitHub上的优秀框架于一体,全部拆离不含任何额外的库导入)
https://github.com/zhiaixinyang/MyFirstApp(Retrofit+RxJava+MVP)
写在前面
这个国庆好像啥事都没有做就已经过去,为了避免整个国庆的浑浑噩噩。那就在国庆的尾巴之时学一下习,记一个知识点。关于ItemDecoration的作用。在很久之前,我一直把ItemDecoration定义在仅仅是画Item的分隔线。
然而当我看了很多大神的代码和思路,才发现ItemDecoration能做的这么多。今天主要就是记录我们经常见到的一个效果,这个效果叫什么名字,还真不清楚,不过看了下面的效果图,觉得就知道了:
此效果的源码放在我的GitHub之中:https://github.com/zhiaixinyang/PersonalCollect
开始
在开始搞这个效果之前,我们先熟悉一下ItemDecoration的简单用法。
public class TestItemDecoration extends RecyclerView.ItemDecoration { /** * 可以实现类似绘制背景的效果,内容在正常的Item下面,被覆盖。正常我们要结合 * getItemOffsets将正常Item错开,免得被正常Item覆盖掉 */ @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); } //可以绘制在内容的上面,覆盖在正常的Item内容 @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDrawOver(c, parent, state); } //实现Item的类似padding的效果,也就是让我们正常的Item进行移动 @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); }}
我们所看到的XX省,其实就是我们的ItemDecoration,也就是分割线做出来的。其实我们,知道这三个方法的用法,通过这三个方法的组合,我们就可以做出这个效果了。
第一步getItemOffsets():
首先,我们在getItemOffsets这个方法之中先进行Item的移动操作,在特定的position之间移开我们用于显示XX省的间隔位置,用作分隔符,并未后续的绘制操作做好准备。
(我们可以通过parent.getChildAdapterPosition(view)
这个方法获取到当前Item的position,拥有了position,我们可以通过外部回调的方式获取对应的Adapter中的对应Data,然后就可以根据我们的业务判断是否需要操作getItemOffsets这个方法。)
@Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); int pos = parent.getChildAdapterPosition(view); //省略一些判空操作,详细内容请移步GitHub:https://github.com/zhiaixinyang/PersonalCollect if (pos == 0 || isFirstInGroup(pos)) { /** * isFirstInGroup(pos)自己的方法,通过外部回调,判断是不是我们想要显示的XX省, * 如果是,移动我们想要显示的高度。 * outRect.top:可以理解为:内边距的高度 */ outRect.top = mGroupHeight; } }
接下来我们就要开始绘制显示XX省的这个Item(本质就是分割线ItemDecoration)。这里我们需要考虑的有点多,我们我们可以看到,在下一个的省替换上一个省显示的时候,我们有一个挤压的效果。
第二部onDrawOver():
因为我们的顶部ItemDecoration有悬浮的效果,所以这里我们使用onDrawOver
这个方法进行绘制。
@Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDrawOver(c, parent, state); final int itemCount = state.getItemCount(); final int childCount = parent.getChildCount(); final int left = parent.getLeft() + parent.getPaddingLeft(); final int right = parent.getRight() - parent.getPaddingRight(); //标记上一个item对应的Group String preGroupName; //当前item对应的Group String currentGroupName = null; //遍历所有的子View(所有的Item) for (int i = 0; i < childCount; i++) { View view = parent.getChildAt(i); int position = parent.getChildAdapterPosition(view); preGroupName = currentGroupName; //如果拿不到我们想要绘制的XX省的名字,跳过遍历过程。也就是正常的Item不做处理(这不是废话么- -!) currentGroupName = getGroupName(position); if (currentGroupName == null || TextUtils.equals(currentGroupName, preGroupName)) continue; //获取需要操作的ItemDecoration的底部距离屏幕顶部的高度 int viewBottom = view.getBottom(); //决定当前顶部第一个悬浮ItemDecoration的bottom float bottom = Math.max(mGroupHeight, view.getTop()); //下一XX省的ItemDecoration一步步逼近我们的首部的悬浮ItemDecoration if (position + 1 < itemCount) { //获取下个GroupName(下一个XX省) String nextGroupName = getGroupName(position + 1); //下一组的第一个View(ItemDecoration)接近头部 if (!currentGroupName.equals(nextGroupName) && viewBottom < bottom) { //bottom最小等于mGroupHeight,而当viewBottom(view.getBottom())小于bottom时,说明当前首都悬浮的ItemDecoration已经被挤压。不断更新bottom值。(因为我们绘制它时需要坐标信息,也就是这个bottom) bottom = viewBottom; } } //根据bottom绘制ItemDecoration c.drawRect(left, bottom - mGroupHeight, right, bottom, mGroutPaint); Paint.FontMetrics fm = mTextPaint.getFontMetrics(); //文字竖直居中显示 float baseLine = bottom - (mGroupHeight - (fm.bottom - fm.top)) / 2 - fm.bottom; c.drawText(currentGroupName, left + mLeftMargin, baseLine, mTextPaint); } }
大概上边的过程看起来很复杂。其实如果理顺了还是很好理解的:
1、我们需要的是绘制我们的XX省的ItemDecoration,因此我们不要判断方式,这里我是通过外部数据源的方式去判断(每个人可能会有不同的处理思路)。
2、然后在onDrawOver()
方法中通过我们的处理思路,遍历所有的View,针对我们要处理的ItemDecoration进行相关绘制。(这里因为,我们使用getItemOffsets()
已经为我们的ItemDecoration移好位置了),通过判断view的getTop,getBottom,mGroupHeight等进行判断是否俩个ItemDecoration进行碰撞,(具体思想可以回过去理解源码),不断记录bottom的值。
3、最后进行正常的Canvas绘制即可。
尾声
理解之后实现起来还是比较的简单。主要还是这种思维模式吧,怎么去理解ItemDecoration分隔符的作用。
明天就要结束假期开始工作了,希望一切顺利!
最后希望各位看官可以star我的GitHub,三叩九拜,满地打滚求star:
https://github.com/zhiaixinyang/PersonalCollect
https://github.com/zhiaixinyang/MyFirstApp
- ItemDecoration实现固定悬浮式Item的思路
- [Java] 固定队列的实现思路
- html固定table表头的实现思路
- vue+jquery+lodash 实现的滑动时顶部悬浮固定
- 利用ItemDecoration给RecyclerView的item添加标题
- Jquery实现相对浏览器位置固定、悬浮
- Android view滑动悬浮固定效果实现
- 顶部样式固定的RecyclerView实现的两种思路
- 悬浮固定
- [html][jQuery]表头固定在顶部的一种实现思路
- HTML 固定div于页面固定位置,实现悬浮按钮。
- android 应用 悬浮窗实现思路
- Fixed固定位置的悬浮div层
- 自动固定顶部的悬浮菜单栏代码
- 自动固定顶部的悬浮菜单栏代码
- 固定位置的Js悬浮窗口
- 使用ItemDecoration 为 RecyclerView设置可 推动的 悬浮导航栏效果
- jquery实现的固定位置下拉隐藏上拉显示悬浮导航菜单特效
- .net mvc Angular2项目 ajax请求返回结果异常处理
- 原创:百度ueditor开源程序的配置方法(VS 2010 asp) 与初学者共享
- AJAX总结
- git SourceTree(remote:invalid username or password,fatal:Authentication falied for 'https:...
- MapReduce总结
- ItemDecoration实现固定悬浮式Item的思路
- knn K近邻算法python实现
- 如何正确使用搜索 -- 他们都说要百度,可为什么我总是百度不到?
- 关系代数
- Uva 455 Periodic Strings
- python_lintcode_115不同的路径 II_112删除排序链表中的重复元素
- HYSBZ3110-K大数查询
- pytorch 几个基本问题
- 数据分析方法