Jetpack Compose之HorizontalPager嵌套动态数量的LazyColumn+Paging3
对于分类展示结构化数据的场景,一般使用Tab+Pager+List的形式。当tab的数量固定时比较好解决,最基础的方式是写n个PagingData和LazyListState:
val recommendState = rememberLazyListState()
val recommendData = uiState.recommendPager.collectAsLazyPagingItems()
val textState = rememberLazyListState()
val textData = uiState.textPager.collectAsLazyPagingItems()
val imageState = rememberLazyListState()
val imageData = uiState.imagePager.collectAsLazyPagingItems()
Column(modifier = Modifier.fillMaxSize()) {
JokeTabs(
tabs = uiState.tabs.map { it.source },
selected = uiState.selectedTab.source,
onClick = {
val index = uiState.tabs.map { it.source }.indexOf(it)
scope.launch { pagerState.animateScrollToPage(index) }
}
)
HorizontalPager(count = uiState.tabs.size, state = pagerState) { page ->
when (page) {
0 -> JokeList(
items = recommendData, state = recommendState,
headerClickListener = headerClickListener,
contentClickListener = contentClickListener,
infoClickListener = infoClickListener
)
1 -> JokeList(
items = textData, state = textState,
headerClickListener = headerClickListener,
contentClickListener = contentClickListener,
infoClickListener = infoClickListener
)
2 -> JokeList(
items = imageData, state = imageState,
headerClickListener = headerClickListener,
contentClickListener = contentClickListener,
infoClickListener = infoClickListener
)
else -> {}
}
}
}
但是这种方法很笨重,需要写很多重复代码,而且无法适应动态数量Tab的形式。解决办法是将LazyColumn的State和PagingData的State放在ViewModel中,而不是放在ui中。
首先,创建UiState:
data class JokeListState(
val listState: LazyListState,
val swipeRefreshState: SwipeRefreshState,
val pagingData: Flow<PagingData<JokeData>>
)
然后在ViewModel中初始化UiState。UiState中三个对象的初始化方法在JetpackCompose提供的remember方法中,没有internal方法,可以直接拿来用。
最后,在ui中引用该UiState:
val owner = LocalLifecycleOwner.current
val uiState by vm.uiState.collectAsStateWithLifecycle(lifecycleOwner = owner)
// Pager中的页面
@Composable
private fun JokeList(
state: JokeListState,
modifier: Modifier = Modifier,
headerClickListener: JokeHeaderClickListener,
contentClickListener: JokeContentClickListener,
infoClickListener: JokeInfoClickListener
) {
val pagingData = state.pagingData.collectAsLazyPagingItems()
val listState = rememberSaveable(saver = LazyListState.Saver) { state.listState } // 注意使用rememberSaveable保存LazyColumn的状态
SwipeRefresh(state = state.swipeRefreshState, onRefresh = { pagingData.refresh() }) {
LazyColumn(modifier = modifier, state = listState) {
items(pagingData) {
it?.let {
JokeCard(
joke = it,
headerClickListener = headerClickListener,
contentClickListener = contentClickListener,
infoClickListener = infoClickListener
)
}
}
}
}
}
以上需要注意的点是需要使用rememberSaveable保存LazyColumn的滑动状态,否则切换Pager的时候会清空该状态
标签:
Android
, Jetpack Compose
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具