如何用Paging3实现全屏宽度可滚动LazyRow并默认显示首元素
问题描述
使用Paging 3实现全屏宽度的可滚动LazyRow,当前pages包含3个元素,但界面默认显示最后一个元素(对应nextKey),需要回滚才能查看之前的元素。
布局代码:
val pages = viewModel.getPages().collectAsLazyPagingItems() LazyRow { items( items = pages, key = { it.id } ) { page -> Card( modifier = Modifier .fillParentMaxWidth() ) { // 内容 } } }
Paging Source代码:
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Page> { println(params.key) val page = params.key ?: 1 val response = repository.getPage( account = account, maxlen = maxlen ) return LoadResult.Page( data = response, prevKey = page.minus(1), nextKey = if (response.isEmpty()) null else page.plus(1), ) }
解决方案
1. 修复分页加载逻辑
你的PagingSource存在核心问题:调用repository.getPage时未传入当前页码page参数,导致无论加载第几页,都会返回相同的数据集。这会触发Paging不断加载后续页,重复添加数据后LazyRow默认停在最后加载的元素位置。
修改PagingSource的load方法,将页码参数传给仓库方法:
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Page> { println(params.key) val page = params.key ?: 1 val response = repository.getPage( account = account, maxlen = maxlen, page = page // 新增页码参数,确保加载对应页的数据 ) return LoadResult.Page( data = response, prevKey = if (page > 1) page.minus(1) else null, // 优化prevKey,避免无效的第0页加载 nextKey = if (response.isNotEmpty()) page.plus(1) else null, ) }
2. 强制滚动到第一个元素
如果业务需要一次性加载所有数据(无需分页),或者修复分页逻辑后仍存在默认定位到最后的问题,可以通过LazyListState手动控制初始滚动位置:
val pages = viewModel.getPages().collectAsLazyPagingItems() val listState = rememberLazyListState() // 当数据加载完成后,自动滚动到第一个元素 LaunchedEffect(pages.itemCount) { if (pages.itemCount > 0) { listState.scrollToItem(index = 0) } } LazyRow(state = listState) { items( items = pages, key = { it.id } ) { page -> Card( modifier = Modifier .fillParentMaxWidth() ) { // 内容 } } }
额外检查点
- 确认
repository.getPage能根据传入的页码返回对应单页数据,而非全部数据 - 确保每个
Page对象的id是唯一值,避免LazyRow的item复用异常
内容的提问来源于stack exchange,提问作者Slava
相关产品推荐
相关产品推荐

