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

如何在SwiftUI中通过滑动手势实现iOS原生计算器同款退格功能

SwiftUI 实现类iOS原生计算器滑动退格功能

你可以按以下方案修改代码,实现和iOS原生计算器完全一致的左右滑动退格效果:

核心修改点

  • 新增字符串类型的输入存储变量,避免Double类型转换带来的格式异常、精度丢失问题,更方便做字符增删操作
  • 优化拖动手势逻辑,改为实时检测滑动位移,每滑动过10pt触发一次退格,支持连续滑动连续删除,匹配原生交互体验
  • 增加边界校验,删除到最后一位时自动置为0,避免出现空值异常

完整修改后代码

import SwiftUI

struct CalculationState {
    var currentNumber: Double = 0
    // 新增字符串存储输入内容,更适配增删操作
    var currentInputString: String = "0"
    let characterLimit = 7
    var storedNumber: Double?
    var storedAction: ActionView.Action?
    
    mutating func appendNumber(_ number: Double) {
        // 超出字符限制直接拦截
        guard currentInputString.count < characterLimit else { return }
        if currentInputString == "0" {
            currentInputString = String(format: "%.f", number)
        } else {
            currentInputString.append(String(format: "%.f", number))
        }
        // 同步更新数值变量
        currentNumber = Double(currentInputString) ?? 0
    }
    
    // 封装退格逻辑
    mutating func backspace() {
        guard currentInputString.count > 1 else {
            currentInputString = "0"
            currentNumber = 0
            return
        }
        currentInputString.removeLast()
        currentNumber = Double(currentInputString) ?? 0
    }
}

struct Home: View {
    @StateObject var viewModel = FetchData()
    @State var state = CalculationState()
    // 记录已处理的滑动位移,实现连续滑动连续删除
    @State private var processedDragOffset: CGFloat = 0
    
    let characterLimit = 9
    let firstBreakDownDivider = 3
    
    var displayedString: String {
        String(state.currentInputString.prefix(characterLimit))
    }
    
    var body: some View {
        // 原有数字键盘布局
        VStack(alignment: .trailing, spacing: 20) {
            Text(displayedString)
                .font(.system(size: 75))
                .foregroundColor(.white)
                .lineLimit(1)
                .padding(.bottom)
                .gesture(
                    DragGesture(minimumDistance: 5, coordinateSpace: .local)
                        .onChanged { value in
                            // 计算本次新增的滑动位移
                            let delta = abs(value.translation.width - processedDragOffset)
                            // 每滑动10pt触发一次退格,可自行调整阈值适配手感
                            if delta >= 10 {
                                state.backspace()
                                processedDragOffset = value.translation.width
                            }
                        }
                        .onEnded { _ in
                            // 滑动结束后重置位移记录
                            processedDragOffset = 0
                        }
                )
            // 你原有其他按钮布局代码补充在此处即可
        }
        .background(Color.black) // 示例背景色,可自行修改
    }
}

如果后续需要支持小数输入,仅需要在CalculationState中新增小数点插入的判断逻辑即可,当前的滑动退格逻辑无需改动,可适配所有字符类型的删除操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 16:48:02