Recycleview的itemdecoration使用
来源:互联网 发布:搜索软件有哪些 编辑:程序博客网 时间:2024/05/21 06:55
最近在做一个项目,有一个页面的功能和微信联系人列表相似,只不过没有右边的abc….。
开始的时候思路是让服务端那边帮我把数据分好组,然后包给我,然后我这边通过ExpandListView去实现,然后将分组的点击事件屏蔽掉。但是且不说服务端大哥不同意,因为他说如果他这边分类的话,要多循环3次,所以不同意,要我客户端自己去分组,无奈啊,然后就自己将请求到的数据分组,然后通过ExpandListView去实现。
最后是效果还行,有点low,而且不能实现那种组被顶上去的感觉。后来就百度啦,发现Recycleview可以定制item间隔的样式,也看了一篇文章(附上链接:http://www.jianshu.com/p/b46a4ff7c10a http://www.jianshu.com/p/3eff217839fc http://www.jianshu.com/p/e742df6f59e2)。
下面自己进行总结一下:
RecycleView可以通过addItemDecoration(ItemDecoration i);方法给item添加间隔,支持定制,因为是add,所以可以添加多个ItemDecoration。也可以使用默认的ItemDecoration,默认样式是灰色间隔。
ItemDecoration的作用:给具体的view添加具体的图画或者layout的位移,对于绘制view之间的分割线,视觉分组边界也是很有用的。
继承ItemDecoration,并实现:
onDraw(Canvas c, RecyclerView parent, RecyclerView.State state),
onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state),
getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
onDraw():该方法会在绘制ItemView之前调用绘制itemdecoration
onDrawOver():该方法是在绘制itemview之后调用绘制itemdecoration,具体体现就是绘制的东西在itemview上面
getItemoffsets:是控制outRect的大小,就是item之间的间隔的矩形。
源码:
// 添加ItemDecoration
public void addItemDecoration(ItemDecoration decor) {
addItemDecoration(decor, -1);
}
// 添加ItemDecoration
public void addItemDecoration(ItemDecoration decor, int index) {
if (mLayout != null) {
mLayout.assertNotInLayoutOrScroll(“Cannot add item decoration during a scroll or”
+ ” layout”);
}
if (mItemDecorations.isEmpty()) {
setWillNotDraw(false);
}
if (index < 0) {
mItemDecorations.add(decor);
} else {
mItemDecorations.add(index, decor);
}
markItemDecorInsetsDirty();
requestLayout();
}
// onLayout 最终会调用到此方法Rect getItemDecorInsetsForChild(View child) { .... final int decorCount = mItemDecorations.size(); for (int i = 0; i < decorCount; i++) { ... mItemDecorations.get(i).getItemOffsets(mTempRect, child, this, mState); ... } ...}@Overridepublic void onDraw(Canvas c) { super.onDraw(c); final int count = mItemDecorations.size(); for (int i = 0; i < count; i++) { mItemDecorations.get(i).onDraw(c, this, mState); }}@Overridepublic void draw(Canvas c) { super.draw(c); final int count = mItemDecorations.size(); for (int i = 0; i < count; i++) { mItemDecorations.get(i).onDrawOver(c, this, mState); }}
可以看出add方法调用后会按照添加的itemDecoration顺序依次调用ItemDecoration的getItemOffsets–>onDraw–>onDrawOver
用法1、给RecycleView设置边距,列举2中使用情况:
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { //介绍3个方法 //1、可以通过下面这个方法拿到当前绘制的itemview的位置 int position = parent.getChildAdapterPosition(view); //2、可以通过下面这个方法拿到itemview的数量 int itemCount = parent.getAdapter().getItemCount(); //3、可以通过下面这个方法拿到recycleview的方向 RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); if(manager instanceOf LinearLayoutManager) int orientation = ((LinearLayoutManager) layoutManager).getOrientation();//然后对position进行判断,并设置间隔大小if(position == 0){//第一个item outRect.set(left,top,right,bottom);}else if(position == itemCount-1){//最后一个item outRect.set(left,top,right,bottom);}else{//其他item的间隔 outRect.set(left,top,right,bottom);}
用法2、绘制分割线,其实就是画矩形,填充颜色
主要是在getitemOffsets方法中设置间隔,然后onDraw方法中计算出上下左右坐标,然后画rect。
用法3、stickHeader效果,类似微信联系人界面,上下滑动时分组会被顶上去的效果。
其实有2种header,一种是和item一个级别,类似divider一样,然后只给统一分组设置header;另一种就是处于item上面一个层级,绘制在item上面一层,然后根据滑动情况顶上去。第一种直接根据ondraw和getitemoffsets方法就可以搞定。第二种可以借助ondrawover方法实现:主要思想就是先根据分组通过onDraw方法绘制每个组的header,然后滑动的时候通过调用ondrawover方法绘制浮在上面的组。下一组的第一个item往上顶的时候,这是一个临界点:一个组的最后一个item的bottom
@Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (如果是头部) { outRect.set(0, (int) mDividerHeight, 0, 0); } } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { View view = parent.getChildAt(i); int position = parent.getChildAdapterPosition(view); // 如果是头 if (position != RecyclerView.NO_POSITION && ((SectionBean) view.getTag()).isGroupStart) { drawHeader(c, parent, view, position); } } } /** * 画头部 * * @param c * @param parent * @param view * @param position */ private void drawHeader(Canvas c, RecyclerView parent, View view, int position) { RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams(); final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); int bottoom = view.getTop() - params.topMargin - Math.round(ViewCompat.getTranslationY(view)); int top = (int) (bottoom - mDividerHeight); // 计算文字居中时候的基线 Rect targetRect = new Rect(left, top, right, bottoom); Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt(); int baseline = (targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2; c.drawRect(left, top, right, bottoom, mPaint); c.drawText(mDatas.get(position).tag, left, baseline, mTextPaint); }
接下来处理浮在上面的header:
@Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { View view = parent.getChildAt(0); View view2 = parent.getChildAt(1); if (view != null && view2 != null) { SectionBean section1 = (SectionBean) view.getTag(); SectionBean section2 = (SectionBean) view2.getTag(); int position = parent.getChildAdapterPosition(view); final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); int bottoom = (int) mDividerHeight; int top = 0; // 判断是否达到临界点 // (第一个可见item是每组的最后一个,第二个可见tiem是下一组的第一个,并且第一个可见item的底部小于header的高度) // 这里直接判断item的底部位置小于header的高度有点欠妥,应该还要考虑paddingtop以及margintop,这里展示不考虑了 if (section1.isGroupEnd && section2.isGroupStart && view.getBottom() <= mDividerHeight) { bottoom = view.getBottom(); top = (int) (bottoom - mDividerHeight); } // 计算文字居中时候的基线 Rect targetRect = new Rect(left, top, right, bottoom); Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt(); int baseline = (targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2; // 背景 c.drawRect(left, top, right, bottoom, mPaint); // 文字 c.drawText(mDatas.get(position).tag, left, baseline, mTextPaint); } }
这样滑动的时候就会实现上一个header被顶上去的效果。
- Recycleview的itemdecoration使用
- RecyclerView.ItemDecoration的使用
- ItemDecoration类的使用
- 很好用的设置RecycleView的ItemDecoration的框架FlexibleDivider
- RecycleView-自定义分割线-ItemDecoration
- 简单粗暴实现RecycleView的瀑布流的粘性头部(非ItemDecoration实现)
- 简单粗暴实现RecycleView的瀑布流的粘性头部(非ItemDecoration实现)
- RecycleView自定义ItemDecoration,实现时间轴效果
- RecycleView深入理解系列之ItemDecoration
- Android RecycleView---- RecycleView的简单使用
- Recycleview的使用
- RecycleView的使用
- RecycleView 的使用
- Android RecycleView的使用
- RecycleView的简单使用
- RecycleView 的使用
- RecycleView的基础使用
- android RecycleView的使用
- Mongodb数据更新命令(update、save)
- c/c++中的inline(内联函数)
- 通过Ajax方式上传文件,使用FormData进行Ajax请求
- 数据中心100G主流应用技术分析
- C++ RSA
- Recycleview的itemdecoration使用
- MySQL实例阻塞分析一例(线程statistics状态)
- IDEA如何自动/手动导入包
- Maven学习笔记二eclipse如何使用 Maven、Maven目录pom.xml文件的解析、maven 和maven项目之间的关系
- leetcode 118
- select函数
- 解决Ubuntu下sublime text3不能输入中文的问题
- 图解二叉树非递归版的前序遍历算法
- hinge loss/支持向量损失的理解