前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android使用BaseSectionQuickAdapter动态生成不规则宫格

Android使用BaseSectionQuickAdapter动态生成不规则宫格

作者头像
Vaccae
发布2021-09-17 10:11:15
1.2K0
发布2021-09-17 10:11:15
举报
文章被收录于专栏:微卡智享微卡智享微卡智享

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为3249,预计阅读6分钟

前言

最近做的新产品设备到了产品摆放的显示,由于客户不同,产品本身的宫格定义也不相同,为了不用每个项目重新改一遍布局,于是就做了个自定义的宫格布局,下面是演示Demo,产品里面还会有别的优化。

实现效果

从上图的红框标的处就是我们自定义的宫格列表,443|4444总长度代表的一共有多少行,中间的|是分格线,标识作用,每个数字代表着每行中的列数,所以443|4444,代表一共有7行,其中1行为4列,2行为4列,3行为3列,分隔线,4行为4列,5行为4列,6行为4列,7行为4列。

代码实现

微卡智享

实现这个效果采用的是BaseSectionQuickAdapter,做为Android的开发者,相信BaseRecyclerViewAdapter应该很多人都在用,这是一个强大而灵活的RecyclerView Adapter,以前一直用原生的Adapter,然后最近项目中使用了PagedListAdapter,效果并是不太理想,所以后来又改用的BaseQuickAdapter,只能说真香。

简单使用方法

builld.gradle中加入

    repositories {
        maven { url 'https://jitpack.io' }
    }
dependencies {
    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.34'
}

最新的版本是3.0.4了,作者用Kotlin重构了些,还解决了一些BUG,不过我在刚用的时候还没研究明白3.0.4的使用,创建的有问题,所以改为了2.9.34

01

定义Bean

一共两个类,一个药品简单信息的,一个设备和对应的格数显示的,其中药品类CDrugs为设备类CDevice的子类,所以在CDevice类中需要继承SectionEntity

package dem.vaccae.basequickadapterdemo.bean

/**
 * 作者:Vaccae
 * 邮箱:3657447@qq.com
 * 创建时间:12:30
 * 功能模块说明:
 */
class CDrugs {

    var colspansize = 15
    var drugs_code = ""
    var drugs_name = ""
    var drugs_specs = ""
    var qty_h = 50
    var qty_l = 20

}
package dem.vaccae.basequickadapterdemo.bean

import com.chad.library.adapter.base.entity.SectionEntity

/**
 * 作者:Vaccae
 * 邮箱:3657447@qq.com
 * 创建时间:12:33
 * 功能模块说明:
 */
class CDevice : SectionEntity<CDrugs> {

    constructor(isHead: Boolean, headstr:String):super(isHead, headstr)

    constructor(item: CDrugs):super(item)

    var dev_seri = 1;

    var dev_gridstr = "555|5555"

    var dev_split = false

}

划重点:

药品类中有一个colspansize的字段,这个是用来设置当前格的占比,其实从图中可以看到,实现宫格来说,一般一行不会超过6个了,所以为了每行不同的格数能够平均显示,能适配1-6都没有问题的,就要求出1-6的最小公倍数,其中2,3,5都是质数,所以2X3X5=30,而30又不能被4整除,4又是2的倍数,所以30再X2即得到60了,并且6也可以被整除。

所以来说设置一个常量60就是每行宫格的固定数,然后能过计算每行显示几列,来求出每列的占比处理即可。

02

SectionQuickAdapter

package dem.vaccae.basequickadapterdemo

import com.chad.library.adapter.base.BaseSectionQuickAdapter
import com.chad.library.adapter.base.BaseViewHolder
import com.chad.library.adapter.base.entity.SectionEntity
import dem.vaccae.basequickadapterdemo.bean.CDevice
import dem.vaccae.basequickadapterdemo.bean.CDrugs

/**
 * 作者:Vaccae
 * 邮箱:3657447@qq.com
 * 创建时间:12:37
 * 功能模块说明:
 */
class SectionQuickAdapter(layoutResId: Int, sectionHeadResId: Int, data: MutableList<CDevice>?) :
    BaseSectionQuickAdapter<CDevice, BaseViewHolder>(layoutResId, sectionHeadResId, data) {


    override fun convert(helper: BaseViewHolder?, item: CDevice?) {
        helper?.let {
            item?.let {
                dev->
                var drugs = dev.t
                it.setText(R.id.tv_drugcode, drugs.drugs_code)
                    .setText(R.id.tv_drugname, drugs.drugs_name)
                    .setText(R.id.tvqty_h, drugs.qty_h.toString())
                    .setText(R.id.tv_qtyl, drugs.qty_l.toString())
            }

        }
    }

    override fun convertHead(helper: BaseViewHolder?, item: CDevice?) {
        helper?.let {
            item?.let { dev ->
                it.setText(R.id.tv_serialno, dev.dev_seri.toString())
                it.setText(R.id.tv_gridstr, dev.dev_gridstr)
                if (item.dev_split) {
                    it.setVisible(R.id.tv_serialno, false)
                } else {
                    it.setVisible(R.id.tv_serialno, true)
                }
            }
        }
    }

}

SectionQuickAdapter设置非常简单,就是是Header时显示什么,不是Header时显示什么,使用BaseQuickAdapter真香的原因就是Adapter里面的代码确实少了很多,用起来方便的很。

03

MainActivity

MainActivity中没有什么特别的,最主要的就是计算生成列表。列表计算时主核心的就是怎么根据字符串进行数据处理。

    fun getGridList(str: String): ArrayList<Int> {
        val list = ArrayList<Int>()
        for (s in str) {
            if (s.toString() == "|") {
                list.add(-1)
            } else {
                list.add(s.toString().toInt())
            }
        }
        return list
    }

getGridList是将传入的字符串转成List<int>的列表,如果是|则设置为-1,代表着是分隔符。

使用for(s in str)遍历String时,每个一s都是char类型了,直接toint得到的数字是Ascii码的数字,所以需要先toString后再toInt。

    fun initData() {
        devices = ArrayList()
        for (i in 1..3) {
            var dev = CDevice(true, i.toString())
            dev.dev_seri = i
            var idx = i % gridstrtype.size
            dev.dev_gridstr = gridstrtype[idx]

            devices.add(dev)

            var list = getGridList(dev.dev_gridstr)
            var rowno = 1;
            for (k in list) {
                if (k > 0) {
                    var spansize = colspan / k
                    for (itemi in 1..k) {
                        var drugs = CDrugs()
                        drugs.drugs_code =
                            i.toString() + rowno.toString() + String.format("%04d", itemi)
                        var drugsidx = itemi % drugnames.size
                        drugs.drugs_name = drugnames[drugsidx]
                        drugs.qty_h = 50
                        drugs.qty_l = 20
                        drugs.colspansize = spansize

                        devices.add(CDevice(drugs))
                    }
                    rowno++
                } else {
                    var dev = CDevice(true, i.toString())
                    dev.dev_seri = i
                    dev.dev_gridstr = "---------------------------------------"
                    dev.dev_split = true;
                    devices.add(dev)
                }
            }
        }
    }

初始化数据时就通过getGridList得到集合后,当前列数大于0时,通过设置的最小公倍数60除当前列数得到的占比。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initData()

        sadapter = SectionQuickAdapter(R.layout.rcl_body, R.layout.rcl_head, devices)
        val gridLayoutManager = GridLayoutManager(this, colspan)
        recyclerview.layoutManager = gridLayoutManager
        recyclerview.adapter = sadapter

        gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
            override fun getSpanSize(position: Int): Int {
                var item = devices.get(position)
                if (item.isHeader) {
                    return colspan
                } else {
                    var drugs = item.t
                    return drugs.colspansize
                }
            }
        }




    }

最后创建GridLayoutManager,每行的格数为60,然后在spanSizeLookup中的getSpanSize中做处理,当是Header时占满60格,如果不是Header时,设置为当到前对象的colspansize即可。

源码地址

https://github.com/Vaccae/AndroidBaseQuickAdapterDemo.git

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微卡智享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 源码地址
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档