DecimalPad Issues SwiftUI

Hello
I have two questions:
  1. I'm using a decimalpad keyboard and when I use the comma the app doesn't recognise it

  2. How do I dismiss the keyboard?

I want that in every country the decimals are written with the comma ( , )

(Can you please write the solution if you know it, thank you for your time)

Code:

Code Block
import SwiftUI
struct BMIView: View {
    
    @State private var height = ""
    @State private var weight = ""
    @Environment(\.presentationMode) var presentationMode
    var inputAfterConvertions: Float {
         let hh = Float(height) ?? 0
         let ww  = Float(weight) ?? 0
         var ris: Float = 0
         if hh > 0 && ww > 0{
         ris = (ww / (hh * hh)) * 1000
            return ris
        }
           return 0
    }
    
    var health: String{
         if inputAfterConvertions < 18.49 && inputAfterConvertions > 0 {
return ""
        }
        else if inputAfterConvertions > 18.5 && inputAfterConvertions < 24.99{
            return ""
        } else if inputAfterConvertions > 25{
            return ""
        }
        
        return ""
    }
    @State var isWriting: Bool = false
    var body: some View {
        NavigationView{
            Form{
                Section(header: Text("Enter your height in cm")){
                    TextField("Input",text: $height)
                        .keyboardType(.decimalPad)
                }
                Section(header: Text("Enter your Weight in kg")){
                    TextField("Input",text: $weight)
                        .keyboardType(.decimalPad)
                }
                Section(header: Text("Check result")){
                    Text("\(inputAfterConvertions, specifier: "%.2f")")
                }
            }
            .navigationBarTitle("BMI")
            .navigationBarItems(trailing:
                                    Button(action: {
                                        presentationMode.wrappedValue.dismiss()
                                    }) {
                                        Image(systemName: "xmark").font(.title).foregroundColor(.blue)
                                    }
            )
        }
    }
}

Thank you very much for your time
Answered by OOPer in 654270022

I'm using a decimalpad keyboard and when I use the comma the app doesn't recognise it

I want that in every country the decimals are written with the comma ( , )

Don't you think it is better for users that they get localized, familiar keypad shown?
Unless you are creating sort of a programming tool, decimal separator should be localized, I think.

You need to do 3 things consistent, when you work with numeric values in UI.
  • Show properly localized keypad (iOS will manage it, and I do not know how to override the behavior of iOS)

  • Read the numeric values using NumberFormatter properly localized

  • Show the numeric values using NumberFormatter properly localized

Code Block
struct BMIView: View {
let numberFormatter: NumberFormatter = {
let nf = NumberFormatter()
nf.locale = Locale.current
//Set up the NumberFormatter as you like...
nf.numberStyle = .decimal
nf.maximumFractionDigits = 1
return nf
}()
@State private var height = ""
@State private var weight = ""
@Environment(\.presentationMode) var presentationMode
var inputAfterConvertions: Float {
//Use NumberFormatter to read numeric values
let hh = numberFormatter.number(from: height)?.floatValue ?? 0 //<-
let ww = numberFormatter.number(from: weight)?.floatValue ?? 0 //<-
var ris: Float = 0
if hh > 0 && ww > 0{
ris = (ww / (hh * hh)) * 1000
return ris
}
return 0
}
//...
var body: some View {
NavigationView{
Form{
Section(header: Text("Enter your height in cm")){
TextField("Input",text: $height)
.keyboardType(.decimalPad)
}
Section(header: Text("Enter your Weight in kg")){
TextField("Input",text: $weight)
.keyboardType(.decimalPad)
}
Section(header: Text("Check result")){
//Use NumberFormatter to show numeric values
Text("\(inputAfterConvertions as NSNumber, formatter: numberFormatter)") //<-
}
}
//...
}



Seems you are trying something called DecimalTextField (regarding issue #2), but you should better always have in mind localization issues unless you write U.S. only apps.


How do I dismiss the keyboard?

Sorry, but I do not know the right solution in pure SwiftUI. Maybe something like UIViewRepresentable (as found in DecimalTextField) would be needed.


One more.

If you already have a similar thread and it is unsolved, you should better consider continuing on the old thread. It is not good for the forums to have many threads unsolved.
Accepted Answer

I'm using a decimalpad keyboard and when I use the comma the app doesn't recognise it

I want that in every country the decimals are written with the comma ( , )

Don't you think it is better for users that they get localized, familiar keypad shown?
Unless you are creating sort of a programming tool, decimal separator should be localized, I think.

You need to do 3 things consistent, when you work with numeric values in UI.
  • Show properly localized keypad (iOS will manage it, and I do not know how to override the behavior of iOS)

  • Read the numeric values using NumberFormatter properly localized

  • Show the numeric values using NumberFormatter properly localized

Code Block
struct BMIView: View {
let numberFormatter: NumberFormatter = {
let nf = NumberFormatter()
nf.locale = Locale.current
//Set up the NumberFormatter as you like...
nf.numberStyle = .decimal
nf.maximumFractionDigits = 1
return nf
}()
@State private var height = ""
@State private var weight = ""
@Environment(\.presentationMode) var presentationMode
var inputAfterConvertions: Float {
//Use NumberFormatter to read numeric values
let hh = numberFormatter.number(from: height)?.floatValue ?? 0 //<-
let ww = numberFormatter.number(from: weight)?.floatValue ?? 0 //<-
var ris: Float = 0
if hh > 0 && ww > 0{
ris = (ww / (hh * hh)) * 1000
return ris
}
return 0
}
//...
var body: some View {
NavigationView{
Form{
Section(header: Text("Enter your height in cm")){
TextField("Input",text: $height)
.keyboardType(.decimalPad)
}
Section(header: Text("Enter your Weight in kg")){
TextField("Input",text: $weight)
.keyboardType(.decimalPad)
}
Section(header: Text("Check result")){
//Use NumberFormatter to show numeric values
Text("\(inputAfterConvertions as NSNumber, formatter: numberFormatter)") //<-
}
}
//...
}



Seems you are trying something called DecimalTextField (regarding issue #2), but you should better always have in mind localization issues unless you write U.S. only apps.


How do I dismiss the keyboard?

Sorry, but I do not know the right solution in pure SwiftUI. Maybe something like UIViewRepresentable (as found in DecimalTextField) would be needed.


One more.

If you already have a similar thread and it is unsolved, you should better consider continuing on the old thread. It is not good for the forums to have many threads unsolved.
I think the user can use an external keyboard via Bluetooth, so it is better to provide for the input of both a dot and a comma:

Code Block  
func replaceComma(str: String) -> Double {
        if let range = str.range(of: ",") {
            let testStr = str.replacingCharacters(in: range, with: ".")
            return Double(testStr) ?? 0
        } else {
            return Double(str) ?? 0
        }
    }


I'm having a similar issue with the decimal keypad. My app requires the user to input a IP address in a text field. I want to support localization, but IP addresses are never writen using commas. Is there a was to force a US only decimal keypad regardless of the user localization (region) settings?

DecimalPad Issues SwiftUI
 
 
Q