学更好的别人,
做更好的自己。
——《微卡智享》
本文长度为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
完