欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android RecyclerView网格布局(支持多种分割线)详解(2)

程序员文章站 2023-12-15 08:36:58
上篇android recyclerview 详解(1)—线性布局 记录了下recyclerview的使用方法,并且讲述了线性布局列表的使用方法,在此基础上加上了万...

上篇android recyclerview 详解(1)—线性布局

记录了下recyclerview的使用方法,并且讲述了线性布局列表的使用方法,在此基础上加上了万能分割线,支持颜色分割线和图片分割线,同时支持对分割线设置线宽。
这篇是总结一下网格布局的使用,同样也支持两种分割线和线宽的设置。

主要的相关类:

1. recyclerview.adapter

2. gridlayoutmanager 网格布局管理器

3. recycleview.itemdecoration 分割线

下面就直接通过一个例子来展示:

先上效果图:

(1) 颜色分割线

Android RecyclerView网格布局(支持多种分割线)详解(2)

看起来还不错吧,根据item的数量去显示格子,当然如果你需要的样式不是三列,这个很简单,只需要在设置
gridlayoutmanager的时候设置相应的列数即可,即:

mmanagerlayout = new gridlayoutmanager(getactivity(), 3);

(2) 图片分割线

Android RecyclerView网格布局(支持多种分割线)详解(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>


未完待续……

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: