Different keyboards show up for KeyboardType .decimalPad

Environment: iOS 26; iPad Mini/Air/Pro

Problem: In a TextField, I am using a keyboard with the type .decimalPad. When I initially tap into the TextField, the "popover" keyboard (i.e. the decimalPad) shows up and focusses the TextField. However, when I click outside the TextField (to dismiss the keyboard), the TextField is still focussed (the keyboard was dismissed though). When reentering in the TextField, another keyboard (from the bottom of the screen) appears (most likely .numeric). Does anybody know how to solve this?

What I already tried: I tried listening to the dismissal of the keyboard to manually set the FocusState to nil. However, the dismissal of the "popover/decimal" keyboard is not recognized as such a dismissal. I also tried to build a custom component out of that, but then I lose the TextField behavior, conflicting with HIG.

Thanks for the post, I would recommend to write a simple focused project showing that part so developers here do not have to create one to reproduce what you are seeing.

Trying to follow you workflow so when the floating/popover .decimalPad keyboard is dismissed by tapping outside of it, the system hides the keyboard UI but fails to automatically resign the firstResponder status of the underlying text field? The TextField still believes it has focus, tapping it a second time causes a state mismatch.

How do you set the TextField? Do you have a FocusState where the TextField to a @FocusState and manually set it to nil (or false) when the user taps the background of your view? If your view is inside a ScrollView, the ScrollView often intercepts taps. You may need to apply the .onTapGesture directly to the content inside the ScrollView

It will be a great idea to see your code and how you manage the onTapGesture as they are many ways to do that.

Looking forward to your reply.

Albert  WWDR

First of all, thank you very much for replying on my thread :) I have prepared two code snippets:

  1. The first one is a very simple one that should demonstrate my problem pretty straightforward
struct ContentView: View {
    @State private var text: String = ""

    var body: some View {
        Form {
            Section {
                LabeledContent(
                    content: {
                        TextField("Text", text: $text)
                            .keyboardType(.decimalPad)
                    },
                    label: {
                        Text("Text")
                    }
                )
                
            }
        }
    }
}
  1. A more sophisticated approach from my project where i specifically saw the problem (as both show the same behavior, i think both might be related)
import SwiftUI

struct Area {
    var length: Double?
    var width: Double?

    var areaString: String {
        guard let l = length, let w = width else { return "-" }
        return String(format: "%.1f cm²", l * w)
    }
}

private enum AreaAttribute: Hashable {
    case length, width

    var label: LocalizedStringKey {
        switch self {
        case .length: "Length"
        case .width: "Width"
        }
    }
}

struct ContentView: View {
    @State private var area: Area = Area()
    @FocusState private var focused: AreaAttribute?

    var body: some View {
        Form {
            Section {
                AreaRow(value: $area.length, label: .length, focused: $focused)
                AreaRow(value: $area.width, label: .width, focused: $focused)
            }
            Section {
                LabeledContent("Area", value: area.areaString)
            }
        }
    }
}

private struct AreaRow: View {
    @Binding var value: Double?
    @State private var text = ""
    @State private var isEditing = false
    let label: AreaAttribute
    var focused: FocusState<AreaAttribute?>.Binding

    var body: some View {
        LabeledContent(label.label) {
            if isEditing {
                HStack {
                    TextField("", text: $text)
                        .keyboardType(.decimalPad)
                        .multilineTextAlignment(.trailing)
                        .focused(focused, equals: label)
                        .onChange(of: text) { _, new in
                            value = Double(new.replacingOccurrences(of: ",", with: "."))
                        }
                    Text("cm").foregroundStyle(.secondary)
                }
            } else {
                Button("Add") {
                    isEditing = true
                    focused.wrappedValue = label
                }
            }
        }
        .onAppear {
            if let value {
                text = String(format: "%.1f", value)
                isEditing = true
            }
        }
    }
}

So basically what happens (I am explaining it now regarding the second code sample) I click on Add -> Floating decimal pad opens up -> i enter a number -> I click outside the decimalPad -> (Textfield stays focussed) -> I click again on the TextField -> Keyboard from bottom slides over (with numbers and special characters). I don't explicitly have a .onTapGesture in the background as (from my understanding) one could rely on the dismissal of the keyboard to automatically reset the FocusState. Hope that helps and thank you again!!

Different keyboards show up for KeyboardType .decimalPad
 
 
Q