1

I have a textfield with the default value of 0.00

When the user taps 1. The textfield should display 0.01

When the user taps 2. The textfield should display 0.12

When the user taps 3. The textfield should display 1.23

When the user taps 4. The textfield should display 12.34

Has anyone done so with SwiftUI?

2
  • sounds like you use arabic ...if so, please be aware that this works automatic by Apple if the user has arabic language settings (and/or format settings) Commented Mar 29, 2020 at 14:01
  • I am not... I need it to fill in a currency textfield, and from right to left, is the standard way of doing it. Commented Mar 29, 2020 at 14:03

4 Answers 4

3

try this

import SwiftUI

class Model: ObservableObject {
    @Published var txt = ""
    var value: Double {
        (Double(self.txt) ?? 0.0) / 100
    }
}

struct ContentView: View {
    @ObservedObject var model = Model()
    var body: some View {
        let binding = Binding<String>(get: { () -> String in
            return String(format: "%.2f", self.model.value)
        }) { (s) in
            var s = s
            s.removeAll { (c) -> Bool in
                !c.isNumber
            }
            self.model.txt = s
        }
        return TextField("0.00", text: binding).keyboardType(.numbersAndPunctuation)
            .padding()
            .border(Color.red)
    }
}

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

here is the result

enter image description here

Sign up to request clarification or add additional context in comments.

8 Comments

your answer works when the user enters the value the FIRST time only. Go try and modify the entry after the keyboard is dismissed and the behavior is totally off!?
also for some reason in a complex UI it doesnt seem to compile. In a simple one like you provided it works minus the issue i just commented above.
@Learn2Code it works the same all the time, as the first time, what trouble you experienced? i am on 11.4 (11E146)
@Learn2Code and it also works in "more complex UI", still the same way.
@Learn2Code i am not your developer, if you have a trouble with my answer, try to do it you own way. I don't remove my own answer just because it could help someone else ... It works as expected, if you like to have 40 valid digits, don't use Double as backend storage.
|
2

I have created a currencyTextField that wraps around a UITextfield. It's not right to left, but you can modify it to be so by removing some cursor code.

Here's the demo

enter image description here

and here's the repo https://github.com/youjinp/SwiftUIKit

2 Comments

great solution but needs to support negative numbers and use decimal rather than double for financial applications
Also seems to be broken with Xcode 13 / iOS 15.
1

in case somebody is still interested in this:

SwiftUI input currency format in a text field (from right to left)

There is no native SwiftUI for this: First Part: You will need to build swifUI component as struct that implements UIViewRepresentable: Here is an interesting example: I converted it to to mask phone number but using simple function instead of custom model. How can you move the cursor to the end in a SwiftUI TextField?

Second Part: You will need to clean (remove in order to adapt this one) the above example little bit and you add this part here. Minor renaming/reconnecting but it works like a charm.

https://stackoverflow.com/a/26569727/15909145 Interesting part the post is done in 2014. Very nice.

Comments

0

The idea is to use some kind of custom proxy for formatting the text on the fly:

struct ContentView: View {
    @State var someNumber = 123

    var body: some View {
        let formattedNumber = Binding<String>(
            get: {
                switch self.someNumber {
                case ..<0: return "???"
                case ..<10: return "0.0\(self.someNumber)"
                case ..<100: return "0.\(self.someNumber)"
                case 100...: return String(format: "%02f", Double(self.someNumber)/100)
                default: return "???"
                }
        },
            set: {
                if let value = NumberFormatter().number(from: $0) {
                    self.someNumber = value.intValue
                }
            }
        )

        return TextField("Number", text: formattedNumber)
      }
}

Warning: This answer contains some UX issues when user is typing, but it answers the original question

Recommendation: For this type of textfields, I recommend to use custom responder that responds to keyboard and text events instead of default TextField

3 Comments

you recommendation is fine but why not use Textfield? TextField is perfect candidate!
Because of the default behavior of the default TextField alongside with the cursor.
yes, i agree ... still some almost fine solution exists, please see my own interpretation :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.