RecyclerView菜单全屏解决方案

前言

目前菜单界面采用RecyclerView + GridLayoutManager实现,最大的好处是修改样式十分方便。但是GridLayoutManager只能在单方向撑满屏幕,如果在有限个item内横向竖向都撑满该怎么做呢?

解决方案

如果是菜单全屏,那么意味着当前界面展示了所有itemView,完全可以抛开缓存机制模仿GridLayoutManager重新写一个LayoutManager。但总觉得还是太麻烦,那就动态计算itemView的高度吧(以下均针对GridLayoutManager横向情况)。

创建一个Adapter,我们重点关注onBindViewHolder函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

var data = emptyList<String>()
set(value) {
field = value
notifyDataSetChanged()
}

private var itemHeight = 0

fun updateItemHeight(height: Int) {
itemHeight = height
}

override fun onBindViewHolder(holder: MenuViewHolder, position: Int) {

val s = data[position]
holder.tvTitle.text = s

val layoutParams = holder.itemView.layoutParams
// 高度可能有盈余,减1保证不可滑动
layoutParams.height = itemHeight - 1
}

在onBindViewHolder函数中,获取到layoutParams,并给height撑满界面时所需的高度即可。
再看一下Activity中计算itemHeight的方法,也十分简单:

1
2
3
4
5
6
7
8
9
private fun measureHeight(): Int {
val row: Int = if (0 == menuData.size % gridLayoutManager.spanCount) {
menuData.size / gridLayoutManager.spanCount
} else {
menuData.size / gridLayoutManager.spanCount + 1
}

return recyclerView.height / row
}

如果item的个数能整除列数,意味着正好撑满最后一行,因此行数为menuData.size / gridLayoutManager.spanCount;如果不能整除就加1。之后设置一下Adapter。

1
2
3
4
5
6
7
btAdd.setOnClickListener {
menuData.add("第${count++}项")
menuAdapter.run {
data = menuData
updateItemHeight(measureHeight())
}
}

最后看一下效果图:
image