SwipeToDismiss 和nestedScroll 不能很好地协同工作 - Jetpack Compose

meh*_*mak 14 android swipe-gesture android-jetpack-compose

我正在尝试实现一个能够通过滑动删除项目的项目列表。我基本上使用过LazyColumnSwipeToDismiss可组合项。

使用默认配置的 LazyColumn 垂直滚动和混合的水平滑动SwipeToDismiss,我主要在尝试垂直滚动时触发 SwipeToDismiss。

为了能够改变灵敏度,SwipeToDismiss我研究了触摸系统的工作原理。据我了解,儿童可组合项应该在消费拖动事件之前询问父母,并且父母可以通过利用nestedScroll在孩子之前消费。但是有一个问题SwipeToDismiss,如果 x&y 轴上的拖动角度在 0 到 45 度之间,它不会将拖动事件分派给父级。所以父母无法消费拖动事件。

通过更改nestedScroll文档页面上的示例,可以重现该问题。只需将项目替换为SwipeToDismiss. 您还可以在下面找到更改后的示例源代码。

我试图了解这是否是一个错误,或者我是否遗漏了某些内容,以及如何使SwipeToDismiss垂直滚动更好地协同工作。

// here we use LazyColumn that has build-in nested scroll, but we want to act like a
// parent for this LazyColumn and participate in its nested scroll.
// Let's make a collapsing toolbar for LazyColumn
    val toolbarHeight = 48.dp
    val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() }
// our offset to collapse toolbar
    val toolbarOffsetHeightPx =

        remember { mutableStateOf(0f) }
// now, let's create connection to the nested scroll system and listen to the scroll
// happening inside child LazyColumn
    val nestedScrollConnection = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                // try to consume before LazyColumn to collapse toolbar if needed, hence pre-scroll
                val delta = available.y
                val newOffset = toolbarOffsetHeightPx.value + delta
                toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f)
                // here's the catch: let's pretend we consumed 0 in any case, since we want
                // LazyColumn to scroll anyway for good UX
                // We're basically watching scroll without taking it
                return Offset.Zero
            }
        }
    }
    Box(
        Modifier
            .fillMaxSize()
            // attach as a parent to the nested scroll system
            .nestedScroll(nestedScrollConnection)
    ) {
        // our list with build in nested scroll support that will notify us about its scroll
        LazyColumn(contentPadding = PaddingValues(top = toolbarHeight)) {
            items(100) { index ->
                val state = remember { DismissState(DismissValue.Default) { true } }
                SwipeToDismiss(state = state, background = {
                    Text(text = "Background", modifier = Modifier.fillMaxWidth().background(color = androidx.compose.ui.graphics.Color.Red))
                }) {
                    Text("I'm item $index", modifier = Modifier
                        .fillMaxWidth()
                        .background(color = Color.Black)
                        .padding(16.dp))
                }

            }
        }
        TopAppBar(
            modifier = Modifier
                .height(toolbarHeight)
                .offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) },
            title = { Text("toolbar offset is ${toolbarOffsetHeightPx.value}") }
        )
    }
Run Code Online (Sandbox Code Playgroud)