微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用户仅在 SwiftUI 文本字段中输入数字货币,同时保留 $ 和 .?

如何解决如何使用户仅在 SwiftUI 文本字段中输入数字货币,同时保留 $ 和 .?

现在,我有以下几点:

private var currencyFormatter: NumberFormatter = {
    let f = NumberFormatter()
    // allow no currency symbol,extra digits,etc
    f.isLenient = true
    f.numberStyle = .currency
    return f
}()

TextField("Total",value: $totalInput,formatter: currencyFormatter)
    .font(.largeTitle)
    .padding()
    .background(Color.white)
    .foregroundColor(Color.black)
    .multilineTextAlignment(.center)

我希望文本字段以 $0.00 作为占位符开始,但是当用户开始输入时,前两个输入将以美分填充...因此 5055 将逐渐显示为:

第 1 步(用户点击 5 次):0.05 美元
第 2 步(用户点击 0):$0.50
第 3 步(用户点击 5):$5.05
第 4 步(用户点击 5):50.55 美元

如果金额超过 999 美元,则会插入逗号。

如何做到这一点?现在我的 totalInput 类型是 Double?。

解决方法

要创建一个允许用户从右到左输入金额的货币字段,您需要一个可观察对象(绑定管理器)、一个货币数字格式化程序,并在每次使用 onChange 方法更改值时进行观察:

import SwiftUI

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct ContentView: View {
    @ObservedObject private var bindingManager = TextBindingManager(amount: 0)
    var decimal: Decimal { bindingManager.text.decimal / pow(10,Formatter.currency.maximumFractionDigits) }
    var maximum: Decimal = 999_999_999.99
    @State private var lastValue: String = ""
    @State private var locale: Locale = .current {
        didSet { Formatter.currency.locale = locale }
    }
    var body: some View {
        VStack(alignment: .leading) {
            TextField(bindingManager.text,text: $bindingManager.text)
                .keyboardType(.numberPad)
                .multilineTextAlignment(.trailing)  // this will keep the text aligned to the right
                .onChange(of: bindingManager.text) { string in
                    if string.decimal > maximum {
                        self.bindingManager.text = lastValue
                    } else {
                        self.bindingManager.text = decimal.currency
                        lastValue = self.bindingManager.text
                    }
                    return
                }
        }
        .padding()
        .onAppear {
            Formatter.currency.locale = locale
        }
    }
}

class TextBindingManager: ObservableObject {
    @Published var text: String = ""
    var amount: Decimal = .zero
    init(amount: Decimal) {
        self.amount = amount
        self.text = Formatter.currency.string(for: amount) ?? "$0.00"
        
    }
}

fileprivate extension Formatter {
    static let currency: NumberFormatter = .init(numberStyle: .currency)
}

extension NumberFormatter {
    convenience init(numberStyle: Style) {
        self.init()
        self.numberStyle = numberStyle
    }
}

extension StringProtocol where Self: RangeReplaceableCollection {
    var digits: Self { filter (\.isWholeNumber) }
}

extension String {
    var decimal: Decimal { Decimal(string: digits) ?? 0 }
}

extension Decimal {
    var currency: String { Formatter.currency.string(for: self) ?? "" }
}

这是相当于我为 UIKit 实现的自定义 CurrencyField 的 SwiftUI。

,

我创建了一个环绕 UITextfield 的组件。

您可以在这里查看https://github.com/youjinp/SwiftUIKit

这是演示

currency text field demo

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。