Jetpack Compose中能否为ExposedDropdownMenu实现分页加载?
我需要给基于API数据的ExposedDropdownMenu添加分页功能,目前用普通List展示选项,想替换成ViewModel中的LazyPagingItems<Division>来实现分页加载。
修改后的DivisionDropDown组件
@OptIn(ExperimentalMaterial3Api::class) @Composable fun DivisionDropDown( divisionPagingItems: LazyPagingItems<Division>, selectedItem: String, itemSelectListener: (String) -> Unit, modifier: Modifier = Modifier ) { var expanded by remember { mutableStateOf(false) } ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = !expanded }, modifier = modifier.wrapContentWidth() ) { OutlinedTextField( value = selectedItem, shape = RoundedCornerShape(12.dp), label = { Text(stringResource(id = R.string.division_of_school)) }, readOnly = true, onValueChange = {}, // 只读状态无需处理输入 trailingIcon = { Icon( painter = painterResource(R.drawable.ic_down), contentDescription = "下拉菜单图标", modifier = Modifier.rotate(if (expanded) 180f else 0f) ) }, maxLines = 1, modifier = Modifier .fillMaxWidth() .wrapContentHeight() .menuAnchor() ) ExposedDropdownMenu( expanded = expanded, onDismissRequest = { expanded = false }, modifier = Modifier .exposedDropdownSize(true) .heightIn(max = 300.dp) // 限制菜单最大高度,避免占满屏幕 ) { LazyColumn { items(divisionPagingItems) { division -> division?.let { DropdownMenuItem( text = { Text(it.name) }, // 假设Division类包含name字段 onClick = { itemSelectListener(it.name) expanded = false }, contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding, ) } } // 处理分页加载状态 divisionPagingItems.apply { when { loadState.refresh is LoadState.Loading -> { item { Box(modifier = Modifier.fillMaxWidth().padding(16.dp)) { CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) } } } loadState.append is LoadState.Loading -> { item { Box(modifier = Modifier.fillMaxWidth().padding(16.dp)) { CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) } } } loadState.append is LoadState.Error -> { val error = divisionPagingItems.loadState.append as LoadState.Error item { Text( text = "加载失败:${error.error.message}", modifier = Modifier.fillMaxWidth().padding(16.dp), textAlign = TextAlign.Center, color = Color.Red ) } } } } } } } }
界面层调用代码修改
@Composable fun SchoolInfoScreen( viewModel: ProfileEditViewModel ) { val divisionPagingItems: LazyPagingItems<Division> = viewModel.divisionState.collectAsLazyPagingItems() var selectedDivision by remember { mutableStateOf("") } // 根据业务逻辑初始化选中项 ConstraintLayout( Modifier .fillMaxWidth() .fillMaxHeight() .padding(horizontal = 16.dp) ) { val (divisionDropDown) = createRefs() DivisionDropDown( divisionPagingItems = divisionPagingItems, selectedItem = selectedDivision, itemSelectListener = { selectedDivision = it }, modifier = Modifier .constrainAs(divisionDropDown) { top.linkTo(parent.top, 32.dp) start.linkTo(parent.start) end.linkTo(parent.end) } ) } }
关键实现要点
- 替换列表容器:将原来的
list.forEach替换为LazyColumn,配合items(divisionPagingItems)渲染分页数据,LazyColumn滚动到底部时会自动触发Paging3的下一页数据请求。 - 参数适配:把组件的
list: List<String>参数改为divisionPagingItems: LazyPagingItems<Division>,直接接收分页数据源。 - 状态反馈:添加分页加载的状态UI,包括刷新加载、追加加载、加载错误的提示,优化用户体验。
- 只读输入处理:只读状态下的
OutlinedTextField无需处理onValueChange逻辑,直接留空即可。 - 菜单高度限制:给ExposedDropdownMenu设置最大高度,避免下拉菜单过长影响界面布局。
内容的提问来源于stack exchange,提问作者Aminul Haque Aome
相关产品推荐
相关产品推荐

