Android RecyclerView网格布局(支持多种分割线)详解(2)
上篇android recyclerview 详解(1)—线性布局
记录了下recyclerview的使用方法,并且讲述了线性布局列表的使用方法,在此基础上加上了万能分割线,支持颜色分割线和图片分割线,同时支持对分割线设置线宽。
这篇是总结一下网格布局的使用,同样也支持两种分割线和线宽的设置。
主要的相关类:
1. recyclerview.adapter
2. gridlayoutmanager 网格布局管理器
3. recycleview.itemdecoration 分割线
下面就直接通过一个例子来展示:
先上效果图:
(1) 颜色分割线
看起来还不错吧,根据item的数量去显示格子,当然如果你需要的样式不是三列,这个很简单,只需要在设置
gridlayoutmanager的时候设置相应的列数即可,即:
mmanagerlayout = new gridlayoutmanager(getactivity(), 3);
(2) 图片分割线
可能有人会说你的列表四周都有分割线,其实在不做特殊处理时左边和上面默认是没有分割线的。后面我会加上四周没有分割线的,其实这两种形式在实际开发中都是常见的,先来看四周都有边线的。
由于recycleview是高度解耦的控件,绘制分割线只和 recycleview.itemdecoration 有关,所以我们只需关心怎么去继承 recycleview.itemdecoration 去实现我们所需的分割线,如下:
这里需要说明的是:颜色分割线和图片分割线原理是完全一样的,图片分割线只是将一张很细的图片传入即可。
public class griddivider extends recyclerview.itemdecoration { private drawable mdividerdarwable; private int mdividerhight = 1; private paint mcolorpaint; public final int[] atrrs = new int[]{android.r.attr.listdivider}; public griddivider(context context) { final typedarray ta = context.obtainstyledattributes(atrrs); this.mdividerdarwable = ta.getdrawable(0); ta.recycle(); } /* int dividerhight 分割线的线宽 int dividercolor 分割线的颜色 */ public griddivider(context context, int dividerhight, int dividercolor) { this(context); mdividerhight = dividerhight; //绘制颜色分割线的画笔 mcolorpaint = new paint(); mcolorpaint.setcolor(dividercolor); } /* int dividerhight 分割线的线宽 drawable dividerdrawable 图片分割线 */ public griddivider(context context, int dividerhight, drawable dividerdrawable) { this(context); mdividerhight = dividerhight; mdividerdarwable = dividerdrawable; } @override public void ondraw(canvas c, recyclerview parent, recyclerview.state state) { super.ondraw(c, parent, state); //画水平和垂直分割线 drawhorizontaldivider(c, parent); drawverticaldivider(c, parent); } public void drawverticaldivider(canvas c, recyclerview parent) { // 这里传入的parent是recycleview,通过它我们可以获取列表的所有的元素, // 这里我们遍历列表中的每一个元素,对每一个元素绘制垂直分割线 final int childcount = parent.getchildcount(); for (int i = 0; i < childcount; i++) { final view child = parent.getchildat(i); //获取当前item布局参数,通过它可以知道该item的精确位置,我们通过这个位置去绘制它的分割线 final recyclerview.layoutparams params = (recyclerview.layoutparams) child.getlayoutparams(); final int top = child.gettop() - params.topmargin; final int bottom = child.getbottom() + params.bottommargin; int left = 0; int right = 0; //左边第一列, if ((i % 3) == 0) { //item左边分割线 left = child.getleft(); right = left + mdividerhight; mdividerdarwable.setbounds(left, top, right, bottom); mdividerdarwable.draw(c); if (mcolorpaint != null) {//如果是颜色分割线 c.drawrect(left, top, right, bottom, mcolorpaint); } //item右边分割线 left = child.getright() + params.rightmargin - mdividerhight; right = left + mdividerhight; } else { //非左边第一列 left = child.getright() + params.rightmargin - mdividerhight; right = left + mdividerhight; } //画分割线 mdividerdarwable.setbounds(left, top, right, bottom); mdividerdarwable.draw(c); if (mcolorpaint != null) { c.drawrect(left, top, right, bottom, mcolorpaint); } } } //....水平分割线与垂直分割线类似,完整代码见下。 }
下面是完整代码:
1. mainactivity
public class mainactivity extends appcompatactivity { private gridfragment mgridfragment; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); //网格 mgridfragment = new gridfragment(); getfragmentmanager().begintransaction().replace(r.id.activity_main, mgridfragment).commit(); }
activity_main
<?xml version="1.0" encoding="utf-8"?> <framelayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent"> </framelayout>
2. gridfragment
public class gridfragment extends fragment implements view.onclicklistener{ private recyclerview mrecycleviewdrawable; private recyclerview mrecycleviewcolor; private linearlayoutmanager mmanagercolor; private linearlayoutmanager mmanagerdrawable; private list<string> mdata; private button mdrawable; private button mcolor; private myrecycleviewadapter mrecycleviewadapter; @nullable @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view view = inflater.inflate(r.layout.fragment_grid_layout, container, false); mrecycleviewdrawable = (recyclerview) view.findviewbyid(r.id.recycleview_drawable); mrecycleviewcolor = (recyclerview) view.findviewbyid(r.id.recycleview_color); mdrawable = (button) view.findviewbyid(r.id.btn_drawable); mdrawable.setonclicklistener(this); mcolor = (button) view.findviewbyid(r.id.btn_color); mcolor.setonclicklistener(this); //设置颜色分割线 mmanagercolor = new gridlayoutmanager(getactivity(), 3); mrecycleviewcolor.setlayoutmanager(mmanagercolor); mrecycleviewcolor.additemdecoration(new griddivider(getactivity(), 20, this.getresources().getcolor(r.color.coloraccent))); //设置图片分割线 mmanagerdrawable = new gridlayoutmanager(getactivity(), 3); mrecycleviewdrawable.setlayoutmanager(mmanagerdrawable); drawable drawable = contextcompat.getdrawable(getactivity(), r.mipmap.divider); mrecycleviewdrawable.additemdecoration(new griddivider(getactivity(), 20, drawable)); //初始化数据 mdata = new arraylist<string>(); initdata(mdata); mrecycleviewadapter = new myrecycleviewadapter(getactivity(), r.layout.item_grid_recycleview, mdata); mrecycleviewcolor.setadapter(mrecycleviewadapter); mrecycleviewdrawable.setadapter(mrecycleviewadapter); return view; } private void initdata(list<string> datalist) { for (int i = 0; i < 16; i++) { datalist.add("item" + i); } } @override public void onclick(view view) { int id = view.getid(); switch (id){ case r.id.btn_drawable: mrecycleviewcolor.setvisibility(view.invisible); mrecycleviewdrawable.setvisibility(view.visible); break; case r.id.btn_color: mrecycleviewcolor.setvisibility(view.visible); mrecycleviewdrawable.setvisibility(view.invisible); break; } } }
3.分割线 griddivider
直接继承 recyclerview.itemdecoration
public class griddivider extends recyclerview.itemdecoration { private drawable mdividerdarwable; private int mdividerhight = 1; private paint mcolorpaint; public final int[] atrrs = new int[]{android.r.attr.listdivider}; public griddivider(context context) { final typedarray ta = context.obtainstyledattributes(atrrs); this.mdividerdarwable = ta.getdrawable(0); ta.recycle(); } /* int dividerhight 分割线的线宽 int dividercolor 分割线的颜色 */ public griddivider(context context, int dividerhight, int dividercolor) { this(context); mdividerhight = dividerhight; mcolorpaint = new paint(); mcolorpaint.setcolor(dividercolor); } /* int dividerhight 分割线的线宽 drawable dividerdrawable 图片分割线 */ public griddivider(context context, int dividerhight, drawable dividerdrawable) { this(context); mdividerhight = dividerhight; mdividerdarwable = dividerdrawable; } @override public void ondraw(canvas c, recyclerview parent, recyclerview.state state) { super.ondraw(c, parent, state); //画水平和垂直分割线 drawhorizontaldivider(c, parent); drawverticaldivider(c, parent); } public void drawverticaldivider(canvas c, recyclerview parent) { final int childcount = parent.getchildcount(); for (int i = 0; i < childcount; i++) { final view child = parent.getchildat(i); final recyclerview.layoutparams params = (recyclerview.layoutparams) child.getlayoutparams(); final int top = child.gettop() - params.topmargin; final int bottom = child.getbottom() + params.bottommargin; int left = 0; int right = 0; //左边第一列 if ((i % 3) == 0) { //item左边分割线 left = child.getleft(); right = left + mdividerhight; mdividerdarwable.setbounds(left, top, right, bottom); mdividerdarwable.draw(c); if (mcolorpaint != null) { c.drawrect(left, top, right, bottom, mcolorpaint); } //item右边分割线 left = child.getright() + params.rightmargin - mdividerhight; right = left + mdividerhight; } else { //非左边第一列 left = child.getright() + params.rightmargin - mdividerhight; right = left + mdividerhight; } //画分割线 mdividerdarwable.setbounds(left, top, right, bottom); mdividerdarwable.draw(c); if (mcolorpaint != null) { c.drawrect(left, top, right, bottom, mcolorpaint); } } } public void drawhorizontaldivider(canvas c, recyclerview parent) { final int childcount = parent.getchildcount(); for (int i = 0; i < childcount; i++) { final view child = parent.getchildat(i); recyclerview.layoutparams params = (recyclerview.layoutparams) child.getlayoutparams(); final int left = child.getleft() - params.leftmargin - mdividerhight; final int right = child.getright() + params.rightmargin; int top = 0; int bottom = 0; // 最上面一行 if ((i / 3) == 0) { //当前item最上面的分割线 top = child.gettop(); //当前item下面的分割线 bottom = top + mdividerhight; mdividerdarwable.setbounds(left, top, right, bottom); mdividerdarwable.draw(c); if (mcolorpaint != null) { c.drawrect(left, top, right, bottom, mcolorpaint); } top = child.getbottom() + params.bottommargin; bottom = top + mdividerhight; } else { top = child.getbottom() + params.bottommargin; bottom = top + mdividerhight; } //画分割线 mdividerdarwable.setbounds(left, top, right, bottom); mdividerdarwable.draw(c); if (mcolorpaint != null) { c.drawrect(left, top, right, bottom, mcolorpaint); } } } }
4. adapter
public class myrecycleviewadapter extends recyclerview.adapter<myrecycleviewadapter.myviewholder> { private layoutinflater mlayoutinflater; private list<string> mdatalist; private int mitemlayout; public myrecycleviewadapter(context context, int itemlayout, list<string> datalist) { mlayoutinflater = layoutinflater.from(context); mitemlayout = itemlayout; mdatalist = datalist; } @override public myrecycleviewadapter.myviewholder oncreateviewholder(viewgroup parent, int viewtype) { return new myviewholder(mlayoutinflater.inflate(mitemlayout, parent, false)); } @override public void onbindviewholder(myrecycleviewadapter.myviewholder holder, int position) { holder.mtextview.settext(mdatalist.get(position)); } @override public int getitemcount() { return mdatalist.size(); } class myviewholder extends recyclerview.viewholder { private textview mtextview; public myviewholder(view itemview) { super(itemview); mtextview = (textview) itemview.findviewbyid(r.id.tv); } } }
adapter 的item布局
<?xml version="1.0" encoding="utf-8"?> <framelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <textview android:id="@+id/tv" android:gravity="center" android:layout_width="match_parent" android:layout_height="60dp"/> </framelayout>
未完待续……
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。