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

Jetpack Compose实现iOS计算器式左滑删除单字符问题排查

解决iOS计算器左滑删除一次删多个数字的问题

问题根源

detectHorizontalDragGestures的回调会在拖动过程中持续触发——只要手指横向拖动的位置发生变化,就会执行一次删除逻辑。这就是为什么一次左滑操作会触发多次删除,导致多个数字被删掉的原因。

修复方案

核心思路是确保一次完整的左滑操作只执行一次删除,以下两种方案都能实现这个目标:

方案一:拖动触发时限制单次执行

通过标记位控制一次拖动过程中只执行一次删除,同时添加最小拖动距离阈值避免误触:

Box(
    contentAlignment = Alignment.BottomEnd,
    modifier = Modifier
        .fillMaxWidth()
        .height(340.dp)
        .pointerInput(Unit) {
            var hasDeleted = false
            detectDragGestures(
                onDragStart = { hasDeleted = false },
                onDragEnd = { hasDeleted = false }
            ) { change, dragAmount ->
                if (!hasDeleted && dragAmount.x < -20) { // 左滑超过20像素才触发
                    hasDeleted = true
                    when {
                        currentValue != "0" && !currentValue.contains("-") && currentValueOnlyWithNumbers.length == 1 -> {
                            currentValue = "0"
                        }
                        currentValue.contains("-") && currentValueOnlyWithNumbers.length == 1 -> {
                            currentValue = "0"
                        }
                        currentValueOnlyWithNumbers.length > 1 -> {
                            currentValue = if (currentValue.contains(" ") && currentValue[currentValue.length - 2] == ' ') {
                                currentValue.dropLast(2)
                            } else {
                                currentValue.dropLast(1)
                            }
                        }
                    }
                    change.consume() // 消费事件,阻止后续触发
                }
            }
        }
)

方案二:拖动结束后统一执行删除

记录拖动的总距离,在手指抬起(拖动结束)时判断是否满足左滑条件,再执行一次删除:

Box(
    contentAlignment = Alignment.BottomEnd,
    modifier = Modifier
        .fillMaxWidth()
        .height(340.dp)
        .pointerInput(Unit) {
            var totalDragX = 0f
            detectHorizontalDragGestures(
                onDragStart = { totalDragX = 0f },
                onDrag = { _, dragAmount ->
                    totalDragX += dragAmount.x
                },
                onDragEnd = {
                    if (totalDragX < -20) { // 总左滑距离超过阈值才执行
                        when {
                            currentValue != "0" && !currentValue.contains("-") && currentValueOnlyWithNumbers.length == 1 -> {
                                currentValue = "0"
                            }
                            currentValue.contains("-") && currentValueOnlyWithNumbers.length == 1 -> {
                                currentValue = "0"
                            }
                            currentValueOnlyWithNumbers.length > 1 -> {
                                currentValue = if (currentValue.contains(" ") && currentValue[currentValue.length - 2] == ' ') {
                                    currentValue.dropLast(2)
                                } else {
                                    currentValue.dropLast(1)
                                }
                            }
                        }
                    }
                }
            )
        }
)

关键细节

  • 拖动距离阈值:设置-20像素的阈值是为了匹配iOS计算器的交互逻辑,避免手指轻微滑动就触发删除。
  • 单次执行控制:无论是标记位还是拖动结束触发,核心都是确保一次左滑只执行一次删除逻辑。
  • 事件消费:使用change.consume()可以阻止手势事件继续传递,避免额外的重复触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:57:11