You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改代码使ModalNavigationDrawer在Checkbox两种状态下均可左滑打开

问题描述

当Checkbox勾选时,绿色区域(MaxBox中的Column组件)会检测从右到左的滑动,每次滑动使计数器加1;取消勾选时,Column停止检测滑动。
无论Checkbox状态如何,用户都应能通过从左到右的滑动打开导航抽屉,但目前Checkbox勾选时,尽管Column并未消费该方向的PointerInputChange事件,导航抽屉仍无法检测到手势。

问题原因

问题出在SwipeModifier的detectDragGestures方法上:默认的detectDragGestures会拦截所有拖拽手势事件,即使你没有调用change.consume()处理非目标方向的滑动,该方法也会阻止事件传递到下层的ModalNavigationDrawer,导致抽屉无法响应左滑手势。

修改方案

仅需修改SwipeModifier.kt文件,调整手势检测逻辑,实现事件的选择性传递:

1. 更新SwipeHandler类

添加公开方法用于判断是否需要消费当前事件:

private class SwipeHandler(
    private val direction: SwipeDirection,
    private val sensitivityFraction: Float,
    private val onSwipe: () -> Unit
) {
    // 原有成员变量和方法保持不变

    // 新增:判断当前偏移是否需要被消费
    fun shouldConsumeEvent(offset: Offset): Boolean {
        return consumeMethod(offset)
    }
}

2. 替换手势检测逻辑

用自定义事件循环替代detectDragGestures,控制事件是否向下传递:

fun Modifier.swipe(
    onSwipe: () -> Unit,
    direction: SwipeDirection = SwipeDirection.LEFT_TO_RIGHT,
    sensitivityFraction: Float = 0.25f
): Modifier = composed {
    val handler = remember(direction, onSwipe, sensitivityFraction) {
        SwipeHandler(direction, sensitivityFraction, onSwipe)
    }

    this
        .pointerInput(Unit) {
            awaitPointerEventScope {
                while (true) {
                    // 等待首次按下事件,允许已被消费的事件(保证下层手势能正常触发)
                    val downEvent = awaitFirstDown(requireUnconsumed = false)
                    handler.onDragStart(downEvent.position)
                    var lastChange: PointerInputChange?

                    do {
                        // 等待拖拽事件
                        val event = awaitPointerEvent()
                        lastChange = event.changes.firstOrNull()

                        lastChange?.let { change ->
                            val dragOffset = change.position - downEvent.position
                            // 处理拖拽逻辑
                            handler.onDrag(change, dragOffset)

                            // 如果当前事件不需要消费,允许传递给下层组件
                            if (!handler.shouldConsumeEvent(dragOffset)) {
                                change.positionChangeConsumed = false
                            }
                        }
                    } while (lastChange?.isConsumed == false)

                    handler.onDragEnd()
                }
            }
        }
        .onSizeChanged { size -> handler.onSizeChanged(size) }
}
修改原理

原来的detectDragGestures会默认拦截所有拖拽事件,无论是否消费都会阻止事件向下传递。修改后的逻辑通过awaitPointerEventScope手动处理事件流:

  • 仅在符合目标滑动方向(右到左)时,才消费事件并触发计数器逻辑
  • 对于左到右的滑动,直接标记事件未被消费,让事件传递到下层的ModalNavigationDrawer,使其能响应打开抽屉的手势

内容的提问来源于stack exchange,提问作者sanitizedUser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 23:24:51