前段时间Compose发布了1.2.0
beta版本,最大的变化之一莫过于LazyLayout
去除了实验性标志。所以接下来,咱们不妨一起看看LazyGrid
的用法
LazyGrid
包含两种微件:LazyVerticalGrid
和LazyHorizontalGrid
。两者内部均由LazyLayout
实现(包括LazyColumn
和LazyRow
也是由LazyLayout
实现的)。不过今天我们不去考虑底层的LazyLayout
,单纯着眼于Grid们
为行文方便,此处仅以LazyVerticalGrid
为例。
最简单的使用如下所示:
@Composable
fun SimpleLazyGrid(){
LazyVerticalGrid(
modifier = Modifier.fillMaxWidth(),
// 固定两列
columns = GridCells.Fixed(2) ,
content = {
items(12){
RandomColorBox(modifier = Modifier.height(200.dp))
}
}
)
}
其中用到的RandomColorBox
仅仅是Box加上随机颜色的背景,唯一注意的是对于LazyLayout,因为涉及到重组过程,所以如果需要记住这个Color(重组时颜色不变),则需要使用rememberSaveable
,其余不再赘述
上面的效果如下
简单的网格布局就实现了
要为子元素之间添加空隙也很简单,指定一下arrangemnt
为spacedBy
即可
//...
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
效果如下
当然也可以添加整体的外边距,设置contentPadding = PaddingValues()
即可,如下:
contentPadding = PaddingValues(12.dp)
上述情况实际上会根据最大宽度来调整,在横屏状态下就可能会惨不忍睹(比如你加载有图片的情况)
所以除了固定列数外,还可以固定宽度,由Compose自动确定要放几列。这个也很简单,就是设置columns
参数为Adaptive
即可
// 固定宽度,自适应列数
columns = GridCells.Adaptive(200.dp) ,
效果如下:
横屏竖屏
可以看到,我们指定的200.dp
是最小值,由于能够容纳一个又无法容纳两个,Compose为我们自动调整为了只放一个,占满全部剩余宽度。
item
和items
均有span
参数,设置此参数即可设定当前元素会占据几格
对于下面的代码:
// 固定列数
columns = GridCells.Fixed(3) ,
content = {
item(span = {
// 占据最大宽度
GridItemSpan(maxLineSpan)
}){
RandomColorBox(modifier = Modifier.height(50.dp))
}
items(12){
RandomColorBox(modifier = Modifier.height(200.dp))
}
},
最上面那个元素就会占据一行,如下:
上面用到的maxLineSpan即为当前行的最大Span,除此之外,还有另一个值maxCurrentLineSpan,二者之间关系如下
columns
其实可以自定义,比方说,我们需要让一行中三个元素,宽度分别为1:2:1,那其实可以这样写。具体细节请参考下面的源码,返回的值即为各元素的宽度组成的List
// 自定义实现1:2:1
columns = object : GridCells {
override fun Density.calculateCrossAxisCellSizes(
availableSize: Int,
spacing: Int
): List<Int> {
// 总共三个元素,所以其实两个间隔
// |元素|间隔|元素|间隔|元素|
// 计算一下所有元素占据的空间
val availableSizeWithoutSpacing = availableSize - 2 * spacing
// 小的两个大小即为剩余空间(总空间-间隔)/4
val smallSize = availableSizeWithoutSpacing / 4
// 大的那个就是除以2呗
val largeSize = availableSizeWithoutSpacing / 2
return listOf(smallSize, largeSize, smallSize)
}
}
效果如下
其余的效果大家就发挥想象啦
如果你想对排列方式也自定义,可以自己实现Arrangement.Vertical
,视频中有给出例子(18:51左右)。这里感觉用处不大,不赘述了
不过也有些情况倒是推荐这么用,比如在item
中包含微件本身和Divider
。一是二者本身语义上就相关联,Divider也不该影响index;二是Divider较小,不影响性能
如果你的列表项有多种不同的类型,可以在item
或items
方法中指定contentType
,这有助于Compose在重组时选择相同Type的微件进行复用,可以提高性能。
contentType = { data.type }
参考的视频中Google其实画了些饼
目前RecyclerView
对应的瀑布流布局Compose
中还没有对应实现,我试图用VerticalLazyGrid
实现然并不行,它摆放的时候会确保每行高度一样……目前的开源库都是多个LazyColumn
并排实现的伪效果。所以还是等吧
阅读量:1851
点赞量:0
收藏量:0