Jetpack Compose中LazyColumn内嵌LazyVerticalGrid实现方案咨询
实现带缩略图的AnswerOption网格布局方案
解决思路
利用Compose中LazyColumn允许嵌套LazyVerticalGrid的特性,通过判断当前问题的选项是否包含带缩略图的条目,动态切换选项的展示布局:有缩略图时用网格展示,无缩略图时保持原列表布局,同时保留原有页面的其他结构。
修改后的完整代码
@Composable fun AssessmentScreen( onClose: (String, String) -> Unit, relatedSubSkillIdsJson: String, uiState: AssessmentUiState, onSelectedOption: (String) -> Unit, onShowAnswerFeedback: (Boolean) -> Unit, onNextQuestion: () -> Unit, onCloseAssessment: () -> Unit, navigateToAndPop: (Pair<String, String>) -> Unit, goBack: () -> Unit, assessmentType: String, ) { val context = LocalContext.current val activity = context.findActivity() val navigationBarHeightDp = activity?.getNavigationBarHeightInDp() ?: 0.dp val blur = if (uiState.isLoading) dimensionResource(dimen.default_screen_blur) else 0.dp val currentArtiIndex = remember { mutableStateOf(0) } if (uiState.questions.isNotEmpty()) { LazyColumn( Modifier .fillMaxSize() .padding( top = dimensionResource(dimen.default_screen_padding), start = dimensionResource(dimen.default_screen_padding), end = dimensionResource(dimen.default_screen_padding) ) .blur(blur) ) { item { CloseAssessment( relatedSubSkillIdsJson = relatedSubSkillIdsJson, uiState = uiState, questionIndex = uiState.currentQuestionIndex, isAnsweredQuestion = uiState.showAnswerFeedback, onCloseAssessment = { onCloseAssessment() }, navigateToAndPop = navigateToAndPop, goBack = goBack ) AssessmentTitle(artiImages[currentArtiIndex.value], assessmentType) QuestionDotsIndicator(uiState.questionAnswersStatus) AssessmentQuestion( thumbnail = uiState.getCurrentQuestionItem().thumbnail, question = uiState.getCurrentQuestionItem().question ) Spacer(modifier = Modifier.height(20.dp)) } val optionsAbcLetterDescription = ('a'..'z').toList() // 判断当前选项是否存在带缩略图的条目 val hasThumbnailOptions = uiState.currentAnswerOptions.any { it.thumbnail.isNotEmpty() } if (hasThumbnailOptions) { // 带缩略图时用网格布局展示选项 item { LazyVerticalGrid( columns = GridCells.Fixed(2), // 可根据需求调整列数,比如用Adaptive实现自适应 horizontalArrangement = Arrangement.spacedBy(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier.fillMaxWidth() ) { itemsIndexed(uiState.currentAnswerOptions) { index, option -> AnswerOption( selectedOptionId = uiState.selectedAnswerId, showFeedback = uiState.showAnswerFeedback, optionLetter = circularCharIteration(optionsAbcLetterDescription, index), option = option, onSelectedOption = { onSelectedOption(it) } ) } } Spacer(modifier = Modifier.height(20.dp)) } } else { // 无缩略图时保持原列表布局 itemsIndexed(uiState.currentAnswerOptions) { index, option -> AnswerOption( selectedOptionId = uiState.selectedAnswerId, showFeedback = uiState.showAnswerFeedback, optionLetter = circularCharIteration(optionsAbcLetterDescription, index), option = option, onSelectedOption = { onSelectedOption(it) } ) Spacer(modifier = Modifier.height(12.dp)) } } item { ChallengeBtn( modifier = Modifier .padding(bottom = navigationBarHeightDp + dimensionResource(dimen.default_screen_padding)), uiState = uiState, navigateToAndPop = navigateToAndPop, onShowAnswerFeedback = { onShowAnswerFeedback(it) }, onCloseAssessment = { onCloseAssessment() }, onNextQuestion = { if (!uiState.isLastQuestion) { currentArtiIndex.value = nextArtiImage(currentArtiIndex.value) onNextQuestion() } } , relatedSubSkillIdsJson = relatedSubSkillIdsJson, ) } } } ProgressBarComponentComposable(isLoading = uiState.isLoading) }
关键修改点说明
- 添加布局判断逻辑:通过
uiState.currentAnswerOptions.any { it.thumbnail.isNotEmpty() }判断是否需要切换到网格布局 - 嵌套LazyVerticalGrid:将网格布局作为
LazyColumn的一个单独item,避免直接嵌套的布局冲突 - 网格布局配置:设置列数、间距等参数,可根据需求调整
GridCells(比如GridCells.Adaptive(150.dp)实现自适应列宽) - 保持原布局兼容:无缩略图时继续使用原有的列表渲染逻辑,保证页面行为一致性
可选扩展
如果需要单独将带缩略图的选项放在网格,不带的放在列表,可以先拆分选项列表:
val thumbnailOptions = uiState.currentAnswerOptions.filter { it.thumbnail.isNotEmpty() } val nonThumbnailOptions = uiState.currentAnswerOptions.filter { it.thumbnail.isEmpty() }
然后分别渲染网格和列表部分即可。
内容的提问来源于stack exchange,提问作者user10625391
相关产品推荐
相关产品推荐

