为 GridLayout 的 RecyclerView 设置 item 间距,实现所有 Item 靠边对齐,中间留白的效果
来源:互联网 发布:淘宝美工怎么自学 编辑:程序博客网 时间:2024/05/22 14:55
今天项目中要实现这样的一个列表效果,因为是列表,那么当然要使用 RecyclerView ,可以轻松实现 GridLayout 的列表效果,但是有一个问题就是 RecyclerView 的 Item 样式不好写,因为 UI 上是要求所有的 Item 靠边显示,中间留出一点空白。
一开始并没有什么思路,很是头疼了一阵,最后多方查找搜索,终于找到了解决方法。办法就是给 RecyclerView 设置ItemDecoration ,从而达到 UI 效果。具体做法就是继承 RecyclerView.ItemDecoration 自定义一 ItemDecoration 代码如下:
public abstract class GridDecoration extends RecyclerView.ItemDecoration { private Paint mPaint; private int lineWidth;//px 分割线宽 public GridDecoration(Context context, float lineWidthDp, @ColorInt int colorRGB) { this.lineWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, lineWidthDp, context.getResources().getDisplayMetrics()); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(colorRGB); mPaint.setStyle(Paint.Style.FILL); } public GridDecoration(Context context, int lineWidthDp, @ColorInt int colorRGB) { this(context, (float) lineWidthDp, colorRGB); } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { //left, top, right, bottom int childCount1 = parent.getChildCount(); // int childCount2 = parent.getLayoutManager().getChildCount(); // int childCount3 = parent.getAdapter().getItemCount(); // Log.e("count", "getChildCount()=" + childCount1 + "-----getLayoutManager().getChildCount()=" + childCount2 + "----getAdapter().getItemCount()=" + childCount3); for (int i = 0; i < childCount1; i++) { View child = parent.getChildAt(i); int itemPosition = ((RecyclerView.LayoutParams) child.getLayoutParams()).getViewLayoutPosition(); boolean[] sideOffsetBooleans = getItemSidesIsHaveOffsets(itemPosition); if (sideOffsetBooleans[0]) { drawChildLeftVertical(child, c, parent); } if (sideOffsetBooleans[1]) { drawChildTopHorizontal(child, c, parent); } if (sideOffsetBooleans[2]) { drawChildRightVertical(child, c, parent); } if (sideOffsetBooleans[3]) { drawChildBottomHorizontal(child, c, parent); } } } private void drawChildBottomHorizontal(View child, Canvas c, RecyclerView parent) { RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); int left = child.getLeft() - params.leftMargin - lineWidth; int right = child.getRight() + params.rightMargin + lineWidth; int top = child.getBottom() + params.bottomMargin; int bottom = top + lineWidth; c.drawRect(left, top, right, bottom, mPaint); } private void drawChildTopHorizontal(View child, Canvas c, RecyclerView parent) { RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); int left = child.getLeft() - params.leftMargin - lineWidth; int right = child.getRight() + params.rightMargin + lineWidth; int bottom = child.getTop() - params.topMargin; int top = bottom - lineWidth; c.drawRect(left, top, right, bottom, mPaint); } private void drawChildLeftVertical(View child, Canvas c, RecyclerView parent) { RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); int top = child.getTop() - params.topMargin - lineWidth; int bottom = child.getBottom() + params.bottomMargin + lineWidth; int right = child.getLeft() - params.leftMargin; int left = right - lineWidth; c.drawRect(left, top, right, bottom, mPaint); } private void drawChildRightVertical(View child, Canvas c, RecyclerView parent) { RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); int top = child.getTop() - params.topMargin - lineWidth; int bottom = child.getBottom() + params.bottomMargin + lineWidth; int left = child.getRight() + params.rightMargin; int right = left + lineWidth; c.drawRect(left, top, right, bottom, mPaint); } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { //outRect 看源码可知这里只是把Rect类型的outRect作为一个封装了left,right,top,bottom的数据结构, //作为传递left,right,top,bottom的偏移值来用的 int itemPosition = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition(); boolean[] sideOffsetBooleans = getItemSidesIsHaveOffsets(itemPosition); //如果是设置左边或者右边的边距,就只设置成指定宽度的一半, // 因为这个项目中的 Grid 是一行二列,如果不除以二的话,那么中间的间距就会很宽, //可根据实际项目需要修改成合适的值 int left = sideOffsetBooleans[0] ? lineWidth/2 : 0; int top = sideOffsetBooleans[1] ? lineWidth : 0; int right = sideOffsetBooleans[2] ? lineWidth/2 : 0; int bottom = sideOffsetBooleans[3] ? lineWidth : 0; outRect.set(left, top, right, bottom); } /** * 顺序:left, top, right, bottom * * @return boolean[4] */ public abstract boolean[] getItemSidesIsHaveOffsets(int itemPosition);}
使用也很简单,用 RecyclerView 的 addItemDecoration() 方法添加 decoration ,需要传入三个参数,分别为:context,要设置的边距宽度(单位:dp),边距颜色。
mRecyclerView.setLayoutManager(new GridLayoutManager(_mActivity, 2)); int color = getResources().getColor(R.color.gray); mRecyclerView.addItemDecoration(new GridDecoration(_mActivity, 8, color) { @Override public boolean[] getItemSidesIsHaveOffsets(int itemPosition) { //顺序:left, top, right, bottom boolean[] booleans = {false, false, false, false}; if (itemPosition == 0) { //因为给 RecyclerView 添加了 header,所以原本的 position 发生了变化 //position 为 0 的地方实际上是 header,真正的列表 position 从 1 开始 } else { switch (itemPosition % 2) { case 0: //每一行第二个只显示左边距和下边距 booleans[0] = true; booleans[3] = true; break; case 1: //每一行第一个显示右边距和下边距 booleans[2] = true; booleans[3] = true; break; } } return booleans; } });
上面的代码中因为我是给 RecyclerView 设置了一个 headView,所以 position 为 0 的时候实际上是 headView,真正 RecyclerView 的 item 位置是从 1 开始的,注意这一点即可。
还有就是我的项目中是每行两列的,如果是每行三列或者更多,需要稍微改下 GridDecoration ,以适配自己的项目,当然也可以进一步封装和完善。
如果有朋友在此基础上封装了更好更完善的 ItemDecoration ,请不吝赐教,可以留言或 Github 提 issue ,谢谢!
Demo 地址 点这里
如果对您有帮助,欢迎 star 一个。
0 0
- 为 GridLayout 的 RecyclerView 设置 item 间距,实现所有 Item 靠边对齐,中间留白的效果
- RecyclerView 设置item之间的间距
- android GridLayout 设置item间距
- RecyclerView 的 item 的间距
- Android中Recyclerview使用14----RecycleView的item间距设置
- Android RecyclerView设置item间距
- android GridLayout 设置item间距方式
- RecyclerView仿GridView的item间距
- android 设置Gridlayout中item的位置
- RecyclerView的行间距&&RecyclerView的Item间距&&
- ListView去掉中间的分割线和设置Item之间的间距
- beamer 中设置 item 之间的间距
- GridView 设置 item 间距的方法
- Android设置Listview每个item的间距
- listview设置每个item的间距
- Android中RecyclerView的item实现动画的效果
- Android中RecyclerView的item运用覆盖view的方法实现item的动画效果
- RecyclerView中item的选中效果
- Redis与Memcached的区别
- CRM系统的两大核心问题
- <opencv学习>之 error LNK2038 RuntimeLibrary 不匹配的解决办法
- Java解决URL中文乱码问题的文章
- JNI学习积累之一 ---- 常用函数大全
- 为 GridLayout 的 RecyclerView 设置 item 间距,实现所有 Item 靠边对齐,中间留白的效果
- zabbix监控cpu参数信息
- caffe多GPU上手
- 51单片机定时/计数器的功能实现
- 二分查找
- 进程学习(1)
- 【Linux】文件描述符和FILE结构体
- Android 通过包名启动另一个应用(APP)
- mysql数据库sql语句的一些常用优化方法