LazyCoumn
是一个类似ListView
和RecyclerView
的View,LazyColumn
仅会呈现屏幕上的可见项目,从而在呈现大列表时提高性能。它可以添加单个item
或者传入数据集合,添加多个Item
,它的使用方法很简单,不需要像原来一样使用Adapter
:
//定义数据集合
val itemsList = (0..20).toList()
val itemsIndexedList = listOf("A", "B", "C")
LazyColumn {
//添加多个item,回调中没有数据的下标
items(itemsList) {
Text("第$it 个Item")
}
//添加单个item
item {
Text("单个 item")
}
//添加多个Item,可以获取到数据的下标
itemsIndexed(itemsIndexedList) { index, item ->
Text("第$index 个Item,value = $item")
}
}
效果:
item
和items
函数接收的是一个**LazyListScope.()**
的DSL
,所以我们可以自己定义LazyColumn item
的内容。
以下内容特别注意!!!
注意:如果想要实现list add
或者remove
后UI也刷新,需要使用mutableStateListOf
或者mutableStateMapOf
来创建list
集合
mutableStateListOf
或者mutableStateMapOf
只能通知添加/删除/替换
这几个事件,所以如果更改了数据中的某个字段时,不会触发Recompose
,可以使用替换
来实现,如:list[index] = list [index].copy(name = "newName")
以上的内容非常重要!!!
contentPadding
contentPadding
可以设置LazyColumn
的边距:
val itemsList = (0..50).toList()
val itemsIndexedList = listOf("A", "B", "C")
LazyColumn(contentPadding = PaddingValues(horizontal = 20.dp, vertical = 20.dp)) {
items(itemsList) {
Text("第$it 个Item")
}
item {
Text("单个 item")
}
itemsIndexed(itemsIndexedList) { index, item ->
Text("第$index 个Item,value = $item")
}
}
contentPadding
接收一个PaddingValues
类型的参数,horizontal
设置的是左右边距,vertical
设置的是上下边距,注意设置的是LazyColumn
的边距,而不是里面item
的边距。
verticalArrangement
verticalArrangement
参数可以设置LazyColumn
垂直排列的方式,其实使用方式和Column效果一致。这里还可以使用它来设置item
的间距:
val itemsList = (0..10).toList()
val itemsIndexedList = listOf("A", "B", "C")
LazyColumn(Modifier.fillMaxHeight(),
contentPadding = PaddingValues(horizontal = 20.dp, vertical = 20.dp),
//设置item的间距为10dp
verticalArrangement = Arrangement.spacedBy(10.dp)) {
items(itemsList) {
Text("第$it 个Item")
}
item {
Text("单个 item")
}
itemsIndexed(itemsIndexedList) { index, item ->
Text("第$index 个Item,value = $item")
}
}
verticalArrangement = Arrangement.spacedBy(10.dp)
用来设置item
之间的间距。
horizontalAlignment
horizontalAlignment
的使用方式和Column
一样:Column horizontalAlignment
reverseLayout
reverseLayout
参数可以改变LazyColumn
的布局方向:true
从上到下,默认的;false
从下到上,第一个item会显示在最下方;
val itemsList = (0..10).toList()
val itemsIndexedList = listOf("A", "B", "C")
LazyColumn(
Modifier.fillMaxHeight(),
reverseLayout = true,
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
items(itemsList) {
Text("第$it 个Item")
}
item {
Text("单个 item")
}
itemsIndexed(itemsIndexedList) { index, item ->
Text("第$index 个Item,value = $item")
}
}
效果:
stickyHeader
stickyHeader
是实验性的API,不稳定也有可能被移除。它可以实现类似吸顶的效果:
val itemsList = (0..30).toList()
val itemsIndexedList = listOf("A", "B", "C")
LazyColumn(
Modifier.fillMaxHeight().fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
itemsIndexed(itemsIndexedList) { index, item ->
Text("第$index 个Item,value = $item")
}
//滑动到这个item时,这个item会悬浮到顶部不动
stickyHeader {
Text("我是Title",modifier = Modifier.fillMaxWidth().background(Color.Red))
}
items(itemsList) {
Text("第$it 个Item")
}
item {
Text("单个 item")
}
}
效果:
state
state
参数可以设置一个LazyListState
,用来监听滚动:
//创建LazyListState
val listState = rememberLazyListState()
val itemsList = (0..30).toList()
val itemsIndexedList = listOf("A", "B", "C")
Column() {
Text(
if (listState.firstVisibleItemIndex < 10) "前10个" else "后10个",
color = Color.Red
)
LazyColumn(
//设置LazyListState
state = listState,
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
items(itemsList) {
Text("第$it 个Item")
}
itemsIndexed(itemsIndexedList) { index, item ->
Text("第$index 个Item,value = $item")
}
}
}
上面的代码会在LazyColumn
滚动到第10个item
的时候,把最上方的Text
文本改成"后10个"
:
listState.firstVisibleItemIndex
获取当前LazyColumn
显示的第一个item
的下标;listState.firstVisibleItemScrollOffset
获取当前LazyColumn
显示的第一个item
的偏移量;
滚动
listState
还可以让LazyColumn
滚动到指定的位置:
//创建LazyListState
val listState = rememberLazyListState()
//创建CoroutineScope
val coroutineScope = rememberCoroutineScope()
val itemsList = (0..30).toList()
val itemsIndexedList = listOf("A", "B", "C")
Column() {
Button(onClick = {
coroutineScope.launch {
listState.scrollToItem(5)
}
}) {
Text(text = "直接滚动")
}
Button(onClick = {
coroutineScope.launch {
listState.animateScrollToItem(10)
}
}) {
Text(text = "带滚动动画")
}
Text(
if (listState.firstVisibleItemIndex < 10) "前10个" else "后10个",
color = Color.Red
)
LazyColumn(
//设置LazyListState
state = listState,
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
items(itemsList) {
Text("第$it 个Item")
}
itemsIndexed(itemsIndexedList) { index, item ->
Text("第$index 个Item,value = $item")
}
}
}
listState.scrollToItem(5)
直接滚动到指定item
的位置,不会有滚动过程的动画listState.animateScrollToItem(10)
滚动到指定item
的位置,会有滚动动画
注意:listState.scrollToItem(5)
和listState.animateScrollToItem(10)
方法都是suspend
挂起函数,所以需要放到协程中执行。