【问题标题】:How can I scroll over sections in Jetpack Compose?如何滚动浏览 Jetpack Compose 中的部分?
【发布时间】:2021-10-15 10:41:57
【问题描述】:

问题:

我有一个屏幕,其中有一列充满(太多)文本字段,这些文本字段可以打包成类别 - 以便用户更容易看到他正在处理的内容。


我的想法是,我可以制作一种选项卡形式,将文本字段放入其中,然后只有用户当前正在处理的选项卡是打开的,其他选项卡关闭但可见。

我想让它像一个垂直的 View Pager 但你可以看到所有要滚动的元素。

要更改视图,您可以滚动或单击要访问的类别。

只有一个标签会一直打开。

问题:

但是我不知道这叫什么或者如何在 Jetpack Compose 中执行此操作 - 所以我想问是否有人可以为我指明正确的方向。

【问题讨论】:

    标签: android kotlin android-jetpack-compose


    【解决方案1】:

    您可以使用rememberSaveable 存储所选项目索引,然后您可以使用AnimatedVisibility 为打开的视图设置动画。要添加我创建的 Modifier.swipeableTopBottom 的滑动,请在 this answer 中查看有关其工作原理的更多详细信息。

    var selectedItem by rememberSaveable { mutableStateOf(0) }
    val itemsCount = 10
    Column(
        verticalArrangement = Arrangement.spacedBy(10.dp),
        modifier = Modifier
            .padding(10.dp)
            .swipeableTopBottom(
                onTop = {
                    selectedItem = (selectedItem - 1).coerceIn(0, itemsCount)
                },
                onBottom = {
                    selectedItem = (selectedItem + 1).coerceIn(0, itemsCount)
                },
            )
    ) {
        repeat(itemsCount) { i ->
            Column(
                Modifier
                    .clickable {
                        selectedItem = i
                    }
                    .fillMaxWidth()
                    .background(Color.DarkGray)
                    .padding(10.dp)
            ) {
                Text("Title $i")
                AnimatedVisibility(visible = i == selectedItem) {
                    Column {
                        repeat(5) { j ->
                            Text("Subtitle $i $j")
                        }
                    }
                }
            }
        }
    }
    

    Modifier.swipeableTopBottom:

    fun Modifier.swipeableTopBottom(onTop: () -> Unit, onBottom: () -> Unit): Modifier = composed {
        var width by rememberSaveable { mutableStateOf(0f) }
        val swipeableState = rememberSwipeableState(
            SwipeDirection.Initial,
            animationSpec = snap()
        )
        val anchorWidth = remember(width) {
            if (width == 0f) {
                1f
            } else {
                width
            }
        }
        val scope = rememberCoroutineScope()
        if (swipeableState.isAnimationRunning) {
            DisposableEffect(Unit) {
                onDispose {
                    when (swipeableState.currentValue) {
                        SwipeDirection.Top -> {
                            onTop()
                        }
                        SwipeDirection.Bottom -> {
                            onBottom()
                        }
                        else -> {
                            return@onDispose
                        }
                    }
                    scope.launch {
                        swipeableState.snapTo(SwipeDirection.Initial)
                    }
                }
            }
        }
        return@composed Modifier
            .onSizeChanged { width = it.width.toFloat() }
            .swipeable(
                state = swipeableState,
                anchors = mapOf(
                    0f to SwipeDirection.Top,
                    anchorWidth / 2 to SwipeDirection.Initial,
                    anchorWidth to SwipeDirection.Bottom,
                ),
                thresholds = { _, _ -> FractionalThreshold(0.3f) },
                orientation = Orientation.Vertical
            )
    }
    
    private enum class SwipeDirection(val raw: Int) {
        Top(0),
        Initial(1),
        Bottom(2),
    }
    

    结果:

    【讨论】:

    • 哇,这正是我想要的,非常感谢! :D
    • @mama 不客气 =)
    • @Phillip Dokhov - 我问了另一个问题,与这个问题相关,并使用您回答中的代码。如果你有兴趣这里是链接stackoverflow.com/questions/69589823/…
    猜你喜欢
    • 2021-12-31
    • 2021-05-26
    • 2021-08-31
    • 2022-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多