Jetpack Compose - LazyRow、LazyColumn

Compose系列文章,请点原文阅读。原文,是时候学习Compose了!

0、介绍

前面我们学习了可以滚动的视图ScrollableRow、ScrollableColumn,当内容过长时可以使其子级进行滚动展示。但是如果遇到超长列表的情况,滚动视图就不可用了,因为滚动视图没有缓存机制,当列表过长的时候,很容易造成内存溢出的情况。
所以这篇文章大就一起来看下Compose给出的解决方案-LazyRow、LazyColumn,官方介绍如下:

  • LazyRow

仅组成和放置 当前可见项 的水平滚动列表。它允许您放置不同类型的子级内容。例如,您可以使用LazyListScope.item添加单个项目,然后使用LazyListScope.items或者LazyListScope.itemsIndexed添加项目列表,后者有当前列表项的索引值。

  • LzayColumn

仅组成和放置 当前可见项 的竖直滚动列表。它允许您放置不同类型的子级内容。例如,您可以使用LazyListScope.item添加单个项目,然后使用LazyListScope.items或者LazyListScope.itemsIndexed添加项目列表,后者有当前列表项的索引值。

也就是说我们可以使用LazyListScope.item来单独添加列表的的内容,或者是添加不同类型的子级内容。

1、属性一览

【目前基于1.0.0-alpha09版本】

  • LazyRow布局的函数如下:
@Composable fun LazyRow(
    modifier: Modifier = Modifier, 
    state: LazyListState = rememberLazyListState(), 
    contentPadding: PaddingValues = PaddingValues(0.dp), 
    reverseLayout: Boolean = false, 
    horizontalArrangement: Arrangement.Horizontal = if (!reverseLayout) Arrangement.Start else Arrangement.End, 
    verticalAlignment: Alignment.Vertical = Alignment.Top, 
    content: LazyListScope.() -> Unit
): Unit

属性参数含义:

参数含义
modifier: Modifier = Modifier应用于布局的修饰符
state: LazyListState = rememberLazyListState()用于控制或观察列表状态的状态对象
contentPadding: PaddingValues = PaddingValues(0.dp)子级内容边界和LazyRow边界的 距离
reverseLayout: Boolean = false反转滚动和布局的方向,当从头到尾组成真正的项目并且LazyListState.firstVisibleItemIndex == 0表示第一个项目位于末尾。
horizontalArrangement: Arrangement.Horizontal = if (!reverseLayout) Arrangement.Start else Arrangement.End布局子级的水平布置。在我们没有足够的项目来填充整个最小尺寸时指定项目的排列方式。
verticalAlignment: Alignment.Vertical = Alignment.Top布局子级的 垂直 对其方式,默认从布局顶部对齐(同Row相关参数的含义)
content: LazyListScope.() -> Unit描述内容的代码块。您可以使用LazyListScope.item方法来添加单个项目,或者使用LazyListScope.items、LazyListScope.itemsIndexed的方法来添加项目列表。
  • LazyColumn的函数如下;
@Composable fun LazyColumn(
    modifier: Modifier = Modifier, 
    state: LazyListState = rememberLazyListState(), 
    contentPadding: PaddingValues = PaddingValues(0.dp), 
    reverseLayout: Boolean = false, 
    verticalArrangement: Arrangement.Vertical = if (!reverseLayout) Arrangement.Top else Arrangement.Bottom, 
    horizontalAlignment: Alignment.Horizontal = Alignment.Start, 
    content: LazyListScope.() -> Unit
): Unit

所有参数都同之前的Row和Column的类似,注意方向上的不同即可,这里不再赘述。

简单说下参数verticalArrangement的场景吧,如下在直播中经常会有公屏区域,如左图中的白框范围,用户发言信息会在这里展示出来,你刚进入直播间的时候可能只有一两条信息,那么这一两条信息需要从底部开始加载,如左图所示,而不可以像右图那样从顶部进行加载,这就很违和了。所以verticalArrangement就是控制这种场景的,你还可以搭配reverseLayout实现其他类似效果。
在这里插入图片描述

以下内容在alpha09中被废弃:
- LazyRowFor、LazyRowForIndexed、LazyColumn、LazyColumnForIndexed

这四个函数都分别继承自LazyRow和LazyColumn,但是他们的功能更加单一,无法使用LazyListScope.item来添加单个项目,只能使用LazyItemScope.(T)来添加列表内容,具体使用方法请见下文。

2、使用示例

横向和竖向的功能类似,这里我们使用 LazyRow 来进行展示,使用item方法添加蓝色的头部和尾部,使用items方法添加列表内容(itemsIndexed会包含列表项的索引值,请根据情况使用),列表项根据索引使用不同的背景色,代码如下:

@Composable
fun LazyRowDemo() {

    val listData = (0..9).toList()
    LazyRow(content = {

        //头部内容
        item {
            Box(
                modifier = Modifier
                    .size(100.dp)
                    .background(Color.Blue),
                contentAlignment = Alignment.Center
            ) {
                Text(text = "头部")
            }
        }

        //列表内容
        items(listData) {
            Box(
                modifier = Modifier
                    .size(100.dp)
                    .background(
                        if (it % 2 == 0) {
                            Color.Red
                        } else {
                            Color.Yellow
                        }
                    ),
                contentAlignment = Alignment.Center
            ) {
                Text(text = "列表项:$it")
            }
        }

        //尾部内容
        item {
            Box(
                modifier = Modifier
                    .size(100.dp)
                    .background(Color.Blue),
                contentAlignment = Alignment.Center
            ) {
                Text(text = "尾部")
            }
        }
    })
}

实现效果如下所示:
在这里插入图片描述
至于其他的四个布局都是继承自LazyRow或者LazyColumn的,而且其内容没有区分item和items、itemsIndexed等属性了,只有单一的items和itemsIndexed属性,方便更加纯粹的实现一个简单列表,这里就不做示例了。

3、版本更新

  • 1.0.0-alpha09
    当前版本去掉了LazyRowFor、LazyRowForIndexed、LazyColumn、LazyColumnForIndexed这几个函数,官方描述为LazyXXXFor可能会错误的开始滚动,建议使用LazyRow、LazyColumn。

4、未解决问题

其实到目前的情况,一个基本的RecyclerView我们已经可以实现了,而且没有Adapter的概念,直接声明你的列表项是什么样子的就可以了,真的是超级简单。
但是在项目实际的使用中,我们可能需要下拉刷新,上拉加载等效果,这个我们后文继续研究,目前仅做了静态的列表展示。
接下的文章我们将结合Jetpack ViewModel、LiveData等来实现一个简单的直播间页面(当然不会有视频预览的画面,就用图片做背景来代替吧,哈哈哈)。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Jetpack Compose 中,LazyColumn 是一个基于 Adapter 模式的组件,它可以根据数据源自动渲染出对应的列表项,并且在滑动过程中会自动回收不可见的列表项,从而保证性能。那么如果你要在 LazyColumn 内部对数据进行增删改查,需要完成以下两个步骤: 1. 确保数据源是可变的 由于 LazyColumn 是根据数据源来渲染列表项的,因此如果你想要在 LazyColumn 内部进行增删改查操作,必须要把数据源定义成可变的,比如 MutableList。 ``` var list by remember { mutableStateOf(mutableListOf<Item>()) } ``` 2. 使用 key 值来实现数据更新 默认情况下,当数据源发生变化时,LazyColumn 并不会自动更新列表项,因为它无法识别哪些列表项需要更新,哪些不需要更新。因此我们需要使用 key 值来告诉 LazyColumn 哪些列表项需要更新。 在 LazyColumn 中,每一个列表项都必须要有一个唯一的 key 值,这个 key 值可以是任意类型的,只要保证每个列表项的 key 值是唯一的即可。当数据源发生变化时,我们只需要通过 key 值来判断哪些列表项需要更新即可。 在 LazyColumn 中,我们可以通过 item() 函数来定义每一个列表项,并且可以通过 key 参数来指定 key 值。当数据源发生变化时,LazyColumn 会自动重新计算每个列表项的 key 值,并且会自动更新需要更新的列表项。 ``` LazyColumn { items(list, key = { item -> item.id }) { item -> // 渲染列表项 } } ``` 需要注意的是,key 值必须要保证唯一性,否则会导致列表项渲染出错。另外,在对数据源进行增删改查操作时,必须要使用可变的数据源,并且还需要调用 remember() 函数来保证数据源的状态能够被保存下来。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值