Compose 组合项 - 滑动列表 LazyColumn、LazyRow

2023-12-20 21:12

本文主要是介绍Compose 组合项 - 滑动列表 LazyColumn、LazyRow,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、概念

可滚动,类似RecyclerView( Column、Row 用 Modifier 设置滚动是相当于ScrollView)。

  • 从 Navigation 返回后丢失状态(跳到头部) :将 LazyListState 提升到 Screen 级别,不用放到 ViewModel 也能恢复滚动状态。(2023-12-14)。
@Composable
fun Demo(dataList: List<String>) {val state = rememberLazyListState()LazyColumn(modifier = Modifier.height(100.dp),state = state,  //管理列表的状态,可通过这个操作列表滚动contentPadding = PaddingValues(horizontal = 5.dp),    //内容内边距reverseLayout = false,  //是否反转显示verticalArrangement = Arrangement.Top,    //排列方式,使用Arrangement.spacedBy(4.dp)就是设置间距horizontalAlignment = Alignment.Start,    //对齐方式flingBehavior = ScrollableDefaults.flingBehavior(),userScrollEnabled = true,   //是否允许滑动) { }
}

二、使用

2.1 列表条目 item()、items()

LazyListScope DSL 提供多种函数来描述列表中的条目,item() 添加单个条目,items() 添加多个条目。

fun Demo(dataList: List<String>) {LazyColumn {//添加单个条目item { Text(text = "单个条目") }//添加多个条目items(5) {index -> Text(text = "条目索引:$index") }//根据数据源创建items(items = dataList,    //可传入、数组、集合、Paging的LazyPagingItemskey = { element ->element.id    //key设为element的唯一值}) { item ->//对条目布局使用该修饰符来对列表的更改添加动画效果Row(Modifier.animateItemPlacement()) {}}//带索引itemsIndexed(dataList) { index: Int, item: String ->Text(text = "$index:$item", modifier = Modifier.padding(1.dp).background(Color.Red))}}
}

2.2 内容内边距 contentPadding

如果对 LazyRow 设置 Modifier.padding() 滑动的时候左右两端会有割裂感(没有滑出屏幕边缘),使用 contentPadding 后初始状态下会显示边距,滑动后是滑出屏幕外。 

LazyColumn(contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp)
) { }

2.3 内容间距 verticalArrangement

如果对 Item 设置padding,会导致相邻的两个 Item 之间是 2 个间距大小,首尾两个 Item 距离容器边缘是 1 个间距大小。

LazyColumn(//使用Arrangement.Top就是排列方式verticalArrangement = Arrangement.spacedBy(4.dp)
) { }

2.4 条目动画

对条目布局使用修饰符来对列表的更改添加动画效果。

items(dataList, key = { it.id }) {Row(Modifier.animateItemPlacement()) { }
}

2.5 黏性标题 stickyHeader()

不会跟随滚动,背景默认透明滑动后会穿透显示。

2.5.1 单个粘性标题

@Composable
fun Dode() {LazyColumn(Modifier.height(100.dp)) {stickyHeader {Text(text = "头部", modifier = Modifier.background(Color.Gray))}items(10) { Text(text = "条目索引:$it") }}
}

2.5.2 多个粘性标题

视频:在手机中上下滚动联系人列表

@Composable
fun ContactsList(grouped: Map<Char, List<Contact>>) {LazyColumn {grouped.forEach { (lastName, contactsForLastName) ->stickyHeader {CharacterHeader(lastName)}items(contactsForLastName) { contact ->ContactListItem(contact)}}}
}

2.6 分页加载(配合 Paging 使用)

详见:Compose - 使用 Paging

Paging 3.0 及更高版本通过 androidx.paging:paging-compose 库提供 Compose 支持。

@Composable
fun Demo() {val pagingItems = viewModel.dataFlow.collectAsLazyPagingItems()LazyColumn(modifier = Modifier.fillMaxSize(),state = rememberLazyListState()) {items(count = pagingItems.itemCount,key = pagingItems.itemKey { it.id }) { index ->//...}}
}ViewModel {val dataFlow by lazy {Pager(PagingConfig(10)) {NewestPagingSource(repository)}.flow.cachedIn(viewModelScope)}
}

2.7 嵌套滚动

应避免内部嵌套一个没有固定大小的同向可滚动子组合项,会抛出 IllegalStateException。可封装在同一个 LazyColumn 中,使用 LazyListScope DSL 传入不同类型的内容,得到相同的效果。

// Throws IllegalStateException
Column(modifier = Modifier.verticalScroll(state)) {LazyColumn {...}
}
LazyColumn {item { Header() }items(data) { item ->Item(item)}item { Footer() }
}

三、列表状态 LazyListState

3.1 滚动位置简单监听

通常只需要监听第一个可见条目的信息,LazyListState 提供了 firstVisibleItemIndex(第一个可见条目的索引)和 firstVisibleItemScrollOffset(第一个可见条目偏移量)属性。

@Composable
fun MessageList(messages: List<Message>) {Box {val listState = rememberLazyListState()LazyColumn(state = listState) {//...}val showButton by remember {derivedStateOf { listState.firstVisibleItemIndex > 0 }}AnimatedVisibility(visible = showButton) {ScrollToTopButton()}}
}

3.2 滚动位置复杂监听

当您需要更新其他界面可组合项时,在组合中直接读取状态非常有效,但在某些情况下,系统无需在同一组合中处理此事件。一个常见的例子是,系统会在用户滚动经过某个点后发送分析事件。为了高效地解决此问题,我们可以使用 snapshotFlow()

val listState = rememberLazyListState()LazyColumn(state = listState) {// ...
}LaunchedEffect(listState) {snapshotFlow { listState.firstVisibleItemIndex }.map { index -> index > 0 }.distinctUntilChanged().filter { it == true }.collect {MyAnalyticsService.sendScrolledPastFirstItemEvent()}
}

3.3 控制滚动位置

LazyListState 通过 scrollToItem() 立即滚动和 animateScrollToItem() 使用动画滚动(平滑滚动)。

@Composable
fun MessageList(messages: List<Message>) {val listState = rememberLazyListState()val coroutineScope = rememberCoroutineScope()LazyColumn(state = listState) {// ...}ScrollToTopButton(onClick = {coroutineScope.launch {listState.animateScrollToItem(index = 0)}})
}

四、提升重组性能

4.1 使用 key

        一般情况下函数的位置是不会发生变化的,Compose编译器能基于调用位置来区分不同的组合项,然后判断内容是否发生变化决定要不要重组。但对于列表来说,在尾部插入还好,如果是在头部或中间,后面的条目由于位置都发生了变化会全部重组,然而现实需求是只需要更新内容发生变化的条目,因此造成了无必要的刷新。

        手动设置 key 为条目的唯一值(如id)后,使得列表能够精准的定位每一个条目函数, 对于内容是否变化能自动通过对象自身的 equals() 来感知,以便跳过重组。这样当数据源发生变化时列表可以高效重组,只需要处理那些发生过变化的条目对应的组合项即可,而不是全部更新。

items(items = dataList,key = { it.id }    //it是dataBean
) { }

4.2 使用 contentType

v1.2版本开始,当列表由多种不同类型的条目组成时,可以为条目指定类型来确保 Compose 不会尝试在属于B类型的组合项上组合A类型的条目。

LazyColumn {items(elements, contentType = { it.type }) {...}
}

这篇关于Compose 组合项 - 滑动列表 LazyColumn、LazyRow的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/517520

相关文章

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

Redis存储的列表分页和检索的实现方法

《Redis存储的列表分页和检索的实现方法》在Redis中,列表(List)是一种有序的数据结构,通常用于存储一系列元素,由于列表是有序的,可以通过索引来访问元素,因此可以很方便地实现分页和检索功能,... 目录一、Redis 列表的基本操作二、分页实现三、检索实现3.1 方法 1:客户端过滤3.2 方法

Python实现将实体类列表数据导出到Excel文件

《Python实现将实体类列表数据导出到Excel文件》在数据处理和报告生成中,将实体类的列表数据导出到Excel文件是一项常见任务,Python提供了多种库来实现这一目标,下面就来跟随小编一起学习一... 目录一、环境准备二、定义实体类三、创建实体类列表四、将实体类列表转换为DataFrame五、导出Da

Python中列表的高级索引技巧分享

《Python中列表的高级索引技巧分享》列表是Python中最常用的数据结构之一,它允许你存储多个元素,并且可以通过索引来访问这些元素,本文将带你深入了解Python列表的高级索引技巧,希望对... 目录1.基本索引2.切片3.负数索引切片4.步长5.多维列表6.列表解析7.切片赋值8.删除元素9.反转列表

基于Redis有序集合实现滑动窗口限流的步骤

《基于Redis有序集合实现滑动窗口限流的步骤》滑动窗口算法是一种基于时间窗口的限流算法,通过动态地滑动窗口,可以动态调整限流的速率,Redis有序集合可以用来实现滑动窗口限流,本文介绍基于Redis... 滑动窗口算法是一种基于时间窗口的限流算法,它将时间划分为若干个固定大小的窗口,每个窗口内记录了该时间

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

c++的初始化列表与const成员

初始化列表与const成员 const成员 使用const修饰的类、结构、联合的成员变量,在类对象创建完成前一定要初始化。 不能在构造函数中初始化const成员,因为执行构造函数时,类对象已经创建完成,只有类对象创建完成才能调用成员函数,构造函数虽然特殊但也是成员函数。 在定义const成员时进行初始化,该语法只有在C11语法标准下才支持。 初始化列表 在构造函数小括号后面,主要用于给

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Spring+MyBatis+jeasyui 功能树列表

java代码@EnablePaging@RequestMapping(value = "/queryFunctionList.html")@ResponseBodypublic Map<String, Object> queryFunctionList() {String parentId = "";List<FunctionDisplay> tables = query(parent

专题二_滑动窗口_算法专题详细总结

目录 滑动窗口,引入: 滑动窗口,本质:就是同向双指针; 1.⻓度最⼩的⼦数组(medium) 1.解析:给我们一个数组nums,要我们找出最小子数组的和==target,首先想到的就是暴力解法 1)暴力: 2)优化,滑动窗口: 1.进窗口 2.出窗口 3.更新值 2.⽆重复字符的最⻓⼦串(medium) 1)仍然是暴力解法: 2)优化: 进窗口:hash[s[rig