使用jetpack撰写动态选项卡创建



如何在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/数据库加载数据之前,它会是什么样子?您可以使用加载指示器、消息等。但是你需要考虑到这一点。

最新更新