0

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?

Learn2Code
  • 1,974
  • 5
  • 24
  • 46
  • 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) – Chris Mar 29 '20 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. – Learn2Code Mar 29 '20 at 14:03

4 Answers4

2

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

user3441734
  • 16,722
  • 2
  • 40
  • 59
  • 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!? – Learn2Code Mar 29 '20 at 18:35
  • 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 Mar 29 '20 at 18:36
  • @Learn2Code it works the same all the time, as the first time, what trouble you experienced? i am on 11.4 (11E146) – user3441734 Mar 29 '20 at 19:53
  • @Learn2Code and it also works in "more complex UI", still the same way. – user3441734 Mar 29 '20 at 19:55
  • if you click on the textfield after you enter a value the the first time, the last two values always remain .00 and any new input just pushes out the rest of the number but it does not populate from the right to left anymore. – Learn2Code Mar 29 '20 at 20:22
  • @Learn2Code video updated :-), i don't see this trouble. – user3441734 Mar 29 '20 at 20:33
  • Try adding a really long number and then editing it again from the most right. – Learn2Code Mar 29 '20 at 20:49
  • @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. – user3441734 Mar 29 '20 at 20:54
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

youjin
  • 2,147
  • 1
  • 12
  • 29
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.

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

Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278