一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 5 天,点击查看活动详情。
假设你有一组大量的列表项数据,如果使用Column
的话,不论该列表项是否正显示在屏幕中,系统均会对其进行绘制,因此很有可能会出现性能问题。
为了解决这个问题,Compose提供了LazyColumn
组件,只有当列表项在视图中可见时,它才会对其中的组件进行绘制。当然,与此对应的,还有一个横向的延迟可组合项组件LazyRow
。
参数
@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(),
content: LazyListScope.() -> Unit
)
参数 | 类型 | 描述 | 可选值 |
---|---|---|---|
modifier | Modifier | 修饰符 | |
state | LazyListState | 用来控制或观察列表状态的状态对象 | 含有两个属性: 1. firstVisibleItemIndex:第一个可见项的索引 2. firstVisibleItemScrollOffset:第一个可见项的滚动偏移量 |
contentPadding | PaddingValues | 列表项的内容内边距 | |
reverseLayout | Boolean | 是否反转布局 | true:从底部开始布局 false:从顶部开始布局 |
verticalArrangement | Arrangement.Vertical | 列表项的垂直安排。 可在列表项之间添加间隔,以及在不足以填满最小尺寸时的排列方式 | |
horizontalAlignment | Alignment.Horizontal | 列表项的水平位置 | |
flingBehavior | FlingBehavior | fling行为的处理逻辑 | |
content | LazyListScope.() -> Unit | 描述内容 | 注意:LazyColumn 跟其他的布局不同,它的content 需要的不是一个@Composable 块,而是一个LazyListScope() 块 |
LazyListScope
@LazyScopeMarker
interface LazyListScope {
/**
* 添加单个item
*/
fun item(key: Any? = null, content: @Composable LazyItemScope.() -> Unit)
/**
* 添加指定数量的item
*/
fun items(
count: Int,
key: ((index: Int) -> Any)? = null,
itemContent: @Composable LazyItemScope.(index: Int) -> Unit
)
/**
* 添加粘性标题
*/
@ExperimentalFoundationApi
fun stickyHeader(key: Any? = null, content: @Composable LazyItemScope.() -> Unit)
}
/**
* 添加一组item
*
* @param items 数据集合
* @param key 标识item的key
* @param itemContent 单个item的内容
*/
inline fun <T> LazyListScope.items(
items: List<T>,
noinline key: ((item: T) -> Any)? = null,
crossinline itemContent: @Composable LazyItemScope.(item: T) -> Unit
) = items(items.size, if (key != null) { index: Int -> key(items[index]) } else null) {
itemContent(items[it])
}
/**
* 添加一组item
*
* @param items 数据集合
* @param key 标识item的key
* @param itemContent 单个item的内容
*/
inline fun <T> LazyListScope.itemsIndexed(
items: List<T>,
noinline key: ((index: Int, item: T) -> Any)? = null,
crossinline itemContent: @Composable LazyItemScope.(index: Int, item: T) -> Unit
) = items(items.size, if (key != null) { index: Int -> key(index, items[index]) } else null) {
itemContent(it, items[it])
}
/**
* 添加一组item
*
* @param items 数据集合
* @param key 标识item的key
* @param itemContent 单个item的内容
*/
inline fun <T> LazyListScope.items(
items: Array<T>,
noinline key: ((item: T) -> Any)? = null,
crossinline itemContent: @Composable LazyItemScope.(item: T) -> Unit
) = items(items.size, if (key != null) { index: Int -> key(items[index]) } else null) {
itemContent(items[it])
}
/**
* Adds an array of items where the content of an item is aware of its index.
*
* @param items 数据集合
* @param key 标识item的key
* @param itemContent 单个item的内容
*/
inline fun <T> LazyListScope.itemsIndexed(
items: Array<T>,
noinline key: ((index: Int, item: T) -> Any)? = null,
crossinline itemContent: @Composable LazyItemScope.(index: Int, item: T) -> Unit
) = items(items.size, if (key != null) { index: Int -> key(index, items[index]) } else null) {
itemContent(it, items[it])
}
举例
联系人列表
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ContactList() {
val list = listOf(
Pair("JY", "觉远"),
Pair("WS", "无色"),
Pair("HZD", "何足道"),
...
Pair("YBH", "杨不悔"),
Pair("CYC", "常遇春"),
Pair("ZYZ", "朱元璋")
).sortedBy { it.first }.groupBy { it.first.first().toString() }
LazyColumn(content = {
list.forEach { (key, dataList) ->
stickyHeader {
...
Text(text = key, ...)
...
}
items(items = dataList) {
...
Text(text = it.second, ...)
...
}
}
})
}