如何在jetpack compose中创建动态选项卡,在我的应用程序中,我需要显示的选项卡数量取决于API响应。但是当我设置TabsRow时,我们需要设置selectedTabIndex值,这就是导致问题的原因。因为在标签数据被加载之前,它试图构建一个没有标签的ui
请帮助我解决这个问题,或者请指导我以正确的方式做。
@Composable
fun CustomTab(viewModel: BeatsViewModel) {
var tabIndex by remember { mutableStateOf(0) }
val beats = viewModel.beatsData.observeAsState().value
ScrollableTabRow(selectedTabIndex = tabIndex) {
beats?.forEachIndexed { index, beatData ->
val selected = tabIndex == index
Tab(selected = selected, onClick = {
tabIndex = index
}) {
Column(
modifier = Modifier
.padding(10.dp)
.height(50.dp)
.fillMaxWidth(),
verticalArrangement = Arrangement.SpaceBetween
) {
Box(
Modifier
.size(24.dp)
.align(Alignment.CenterHorizontally)
.background(color = if (selected) Color.Red else Color.White)
)
Text(
text = beatData.mBeatName,
style = MaterialTheme.typography.body1,
modifier = Modifier.align(Alignment.CenterHorizontally)
)
}
}
}
}
}
这会抛出如下错误(甚至在我的viewmodel post任何值到beatsData之前)-
Process: in.bizom.android, PID: 23133
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:437)
at androidx.compose.material.TabRowKt$ScrollableTabRow$1.invoke(TabRow.kt:230)
at androidx.compose.material.TabRowKt$ScrollableTabRow$1.invoke(TabRow.kt:228)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.material.TabRowKt$ScrollableTabRow$2$1$2$3.invoke(TabRow.kt:299)
at androidx.compose.material.TabRowKt$ScrollableTabRow$2$1$2$3.invoke(TabRow.kt:298)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2$1$1.invoke(SubcomposeLayout.kt:251)
at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2$1$1.invoke(SubcomposeLayout.kt:251)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.ComposerKt.invokeComposable(Composer.kt:3337)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2582)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2571)
at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:247)
at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2571)
at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:2522)
at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:478)
at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:748)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:2987)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:2987)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:433)
at androidx.compose.ui.layout.SubcomposeLayoutState.subcomposeInto(SubcomposeLayout.kt:269)
at androidx.compose.ui.layout.SubcomposeLayoutState.access$subcomposeInto(SubcomposeLayout.kt:154)
at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:244)
at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:241)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.withNoObservations(SnapshotStateObserver.kt:142)
at androidx.compose.ui.node.OwnerSnapshotObserver.withNoSnapshotReadObservation$ui_release(OwnerSnapshotObserver.kt:55)
at androidx.compose.ui.node.LayoutNode.withNoSnapshotReadObservation$ui_release(LayoutNode.kt:1175)
at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:241)
at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:235)
at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose$ui_release(SubcomposeLayout.kt:224)
at androidx.compose.ui.layout.SubcomposeLayoutState$Scope.subcompose(SubcomposeLayout.kt:490)
at androidx.compose.material.TabRowKt$ScrollableTabRow$2$1$2.invoke(TabRow.kt:298)
at androidx.compose.material.TabRowKt$ScrollableTabRow$2$1$2.invoke(TabRow.kt:273)
at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:68)
at androidx.compose.ui.layout.SubcomposeLayoutState$createMeasurePolicy$1$measure$1.placeChildren(SubcomposeLayout.kt:367)
at androidx.compose.ui.node.LayoutNode$layoutChildren$1.invoke(LayoutNode.kt:993)
at androidx.compose.ui.node.LayoutNode$layoutChildren$1.invoke(LayoutNode.kt:978)
您需要为该屏幕定义一个空状态视图。在从API/数据库加载数据之前,它会是什么样子?您可以使用加载指示器、消息等。但是你需要考虑到这一点。