文章目录
- 前言
- LazyListScope作用域 用来干什么?
- LazyColumn组件含义?
- LazyColumn的基本使用
- LazyColumn Padding设置边距
- LazyColumn 设置边距 (contentPadding)
- LazyColumn 为每个子项设置边距 (Arrangement.spacedBy())
- LazyColumn 根据 rememberLazyListState 记录item位置
- 根据 items函数 新增 一个key参数,增加和删除操作时,提高页面性能问题
- LazyRow的含义
- LazyRow的使用
- 总结
前言
现在应用市场上很多产品都少不了列表展示需求场景,例如通讯录,短信,音乐列表等等。
所以本篇文章讲解的组件 - 列表 (LazyList 和 LazyRow )
在了解 LazyList 和 LazyRow 之前,我们先了解下 LazyListScope作用域
LazyListScope作用域 用来干什么?
LazyColumn 和 LazyRow 内部都是继承 LazyList组件 实现,但 LazyList 不能直接使用
LazyList 的 content 是一个 LazyListScope.() -> Unit 类型的作用域
LazyListScope 提供了 item , items(Int) , item(List) , itemsIndexed(List) 扩展函数来展示列表内容
item:展示单项数据
items(Int):展示多项整型数据
items(List) 展示一组集合数据
itemsIndexed(List) 展示一组集合数据,并且带有下标
val list = ('A'..'Z').map { it.toString() }
LazyColumn{item { Text(text = "first item") }items(10){ index ->Text(text = "$index")}item { Text(text = "last item") }items(list){ item ->Text(text = item)}itemsIndexed(list){ index, item ->Text(text = "$index/$item")}
}
LazyColumn组件含义?
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, //子组件横向对齐方式flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(), //fling行为处理逻辑userScrollEnabled: Boolean = true, //是否允许滑动content: LazyListScope.() -> Unit //LazyList作用域
)
LazyColumn的基本使用
LazyColumn 组件 相比传统的 RecyclerView 少写很多代码
RecyclerView 需要在xml中声明一个RecyclerView控件,再在xml中声明一个子控件,再创建一个适配器Adapter,最后在activity中 指定 RecyclerView 的布局类型,再为其填充数据
LazyColumn 就很简单了,看如下代码的实现,就知道了
@Composable
fun LazyColumnList() {LazyColumn {items(20) { i ->Text(text = "Item $i",modifier = Modifier.fillMaxWidth().height(60.dp))}}
}
LazyColumn Padding设置边距
Padding可以设置列表边距,但是会出现切割现象,我们来看下代码
val list = ('A'..'Z').map { it.toString() }LazyColumn {itemsIndexed(list) { index, letter ->Card(modifier = Modifier.width(120.dp).height(200.dp).padding(10.dp)) {Text(text = "$index $letter",textAlign = TextAlign.Center,fontSize = 20.sp,modifier = Modifier.fillMaxSize().wrapContentHeight(Alignment.CenterVertically))}}}
现在看下运行代码的效果:
注:
从上图可以看出来最后一个出现了被切割现象,那如何解决这个问题呢?
那就要用到 LazyColumn 提供的 contentPadding 解决
LazyColumn 设置边距 (contentPadding)
LazyColumn 设置边距用的是contentPadding,能保证上下两边的边距相等同时,还不会在滚动的时候,出现切割现象
val list = ('A'..'Z').map { it.toString() }
LazyColumn(contentPadding = PaddingValues(top = 40.dp, start = 10.dp, bottom = 40.dp, end = 10.dp)) {itemsIndexed(list) { index, letter ->Card(modifier = Modifier.fillMaxWidth().height(120.dp)
// .padding(10.dp)) {Text(text = "$index $letter",textAlign = TextAlign.Center,fontSize = 20.sp,modifier = Modifier.fillMaxSize().wrapContentHeight(Alignment.CenterVertically))}}}
现在再看下效果图:
注:
现在可以看出来,没有切割的现象了,但有个问题,中间没有了间距
Lazy Layout提供了专门给子项之间设置边距的属性,使用Arrangement.spacedBy()即可
LazyColumn 为每个子项设置边距 (Arrangement.spacedBy())
Arrangement.spacedBy() 专门为子项设置边距
val list = ('A'..'Z').map { it.toString() }
LazyColumn(contentPadding = PaddingValues(top = 40.dp, start = 10.dp, bottom = 40.dp, end = 10.dp),verticalArrangement = Arrangement.spacedBy(20.dp)) {itemsIndexed(list) { index, letter ->Card(modifier = Modifier.fillMaxWidth().height(120.dp)) {Text(text = "$index $letter",textAlign = TextAlign.Center,fontSize = 20.sp,modifier = Modifier.fillMaxSize().wrapContentHeight(Alignment.CenterVertically))}}
}
效果图如下:
LazyColumn 根据 rememberLazyListState 记录item位置
有时候有这样的需求:让组件随着列表的滚动进行一些额外的响应。如随着滚动隐藏和显示某个组件
这时候 rememberLazyListState 就排上用场了
以下是rememberLazyListState 源码:
@Composable
fun rememberLazyListState(initialFirstVisibleItemIndex: Int = 0, //第一个可见子项元素的下标initialFirstVisibleItemScrollOffset: Int = 0 //第一个可见子项元素的偏移距离
): LazyListState {return rememberSaveable(saver = LazyListState.Saver) {LazyListState(initialFirstVisibleItemIndex,initialFirstVisibleItemScrollOffset)}
}
根据列表第一项可见显示组件,不可见隐藏组件
@SuppressLint("FrequentlyChangedStateReadInComposition")
@Composable
fun ListLayout() {val state = rememberLazyListState()Box {val list = ('A'..'Z').map { it.toString() }LazyColumn(state = state,contentPadding = PaddingValues(top = 40.dp, start = 10.dp, bottom = 40.dp, end = 10.dp),verticalArrangement = Arrangement.spacedBy(20.dp)) {itemsIndexed(list) { index, letter ->Card(modifier = Modifier.fillMaxWidth().height(120.dp)) {Text(text = "$index $letter",textAlign = TextAlign.Center,fontSize = 20.sp,modifier = Modifier.fillMaxSize().wrapContentHeight(Alignment.CenterVertically))}}}if (state.firstVisibleItemIndex == 0) {FloatingActionButton(onClick = {},shape = CircleShape,modifier = Modifier.align(Alignment.CenterEnd).padding(20.dp)) {Icon(Icons.Filled.Star, "Add Button")}}}
}
根据 items函数 新增 一个key参数,增加和删除操作时,提高页面性能问题
因为compose中往列表添加一项数据,就会整体往后移,数据越多,页面性能越差
所以Google给出了一个解决方案:在items函数添加一个唯一标识的key
@Composable
fun SubVerticalScrollable() {val list = ('A'..'Z').map { it.toString() }LazyColumn(modifier = Modifier.height(300.dp)) {items(list, key = { it }) { letter ->...}}
}
LazyRow的含义
LazyRow 和 LazyColumn用法基本相同,唯一不同的是横向布局的列表组件
@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, //子组件纵向对齐方式flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(), //fling行为处理逻辑userScrollEnabled: Boolean = true, //是否允许滑动content: LazyListScope.() -> Unit //LazyList作用域
)
LazyRow的使用
val list = ('A'..'Z').map { it.toString() }
LazyRow(state = state,contentPadding = PaddingValues(top = 40.dp, start = 10.dp, bottom = 40.dp, end = 10.dp),horizontalArrangement = Arrangement.spacedBy(20.dp)) {itemsIndexed(list) { index, letter ->Card(modifier = Modifier.height(300.dp).width(120.dp)) {Text(text = "$index $letter",textAlign = TextAlign.Center,fontSize = 20.sp,modifier = Modifier.fillMaxSize().wrapContentHeight(Alignment.CenterVertically))}}
}
到这里,基本上Lazy Layout 基本上覆盖到了,还有什么问题,欢迎反馈和评论区留言
总结
- LazyListScope作用域提供了 item , items(Int) , item(List) , itemsIndexed(List) 扩展函数来展示列表内容
- LazyColumn 就是一个纵向滚动列表
- contentPadding 设置列表组件的整个内容的边距
- Arrangement.spacedBy() 为列表的每个子项设置边距
- LazyColumn 根据 rememberLazyListState 记录第一个可见子项元素位置
- items函数 新增 一个key参数,设置唯一性,增加和删除操作时,性能得到优化和提高
- LazyRow 是一个横向布局的列表组件,用法和 LazyColumn一致