How to dismiss keyboard after entering text in a textfield?

I am developing an app (SwiftUI newbie) and i have a textfield on my form that when a user selects the field the numeric keyboard pops-up for the user to enter in their value. After they do this and move on to the other objects on the form (picker, etc.); the keyboard stays displayed; how can I get the keyboard to dismiss (there is no button on the keypad like the iPad has)?


Please help and thanks in advance. I am looking for the correct way to handle this type of condition and haven't been able to find anything that makes sense. I am surprised this is not a more common question.


Thanks,


Kevin

Call


            TextField("Name...", text: self.$name) {
                // Called when the user tap the return button
                // see `onCommit` on TextField initializer.
                UIApplication.shared.endEditing()
            }


where endEditing

extension UIApplication {
    func endEditing() {
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}



credit. https://stackoverflow.com/questions/56491386/how-to-hide-keyboard-when-using-swiftui


Very simple example:

struct LiveView: View {

    @State private var name = "name"

    var body: some View {
        VStack {
            TextField("Name...", text: self.$name) {
                UIApplication.shared.endEditing()
            }
        }.onTapGesture {
            self.endEditing()
        }
    }

    private func endEditing() {
        UIApplication.shared.endEditing()
    }

}


Tested on SwiftUI "simulator" on OSX 10.14.6

I'm fighting the same issue. This approach works well to dismiss the keyboard. BUT, after the keyboard is dismissed the two segmentd pickers that I use next on the SwiftUI Form do not work. I can have the keyboard dismissed, or I can have the Pickers work but not both using this approach.


I'm a newbie can someone point me in the right direction and give me a piece of sample code that I can insert to restore the response of the Pickers in the following two sections of the Form after dismissing the keyboard. Have tried many things but like KJFGA says none of the many search results I have found are complete and/or make any sense.


It can't be this hard!


Please help

Could you show the complete view code, I cannot reproduce the problem.

Claude31,


Thanks for the quick reply! I appreciate it. Here's the ContentView code in question:


//---------------------------------------------------------

//

// ContentView.swift

// SplitTheTab

//

// Created by Dale Puckett on 12/21/19.

// Copyright © 2019 Dale Puckett. All rights reserved.

//



import SwiftUI



extension UIApplication {

func endEditing() {

sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)

}

}



/* extension UIApplication {

func resumeEditing() {

sendAction(#selector(UIResponder.becomeFirstResponder), to: nil, from: nil, for: onTapGesture)

}

} */



struct ContentView: View {

@State private var checkAmount = ""

@State private var tipPercentage = 2

let tipPercentages = [10, 15, 20, 25, 0]

@State private var numberOfPeople = 0

let numPayees = [1, 2, 3, 4, 5, 6, 7, 8, 9]

var totalPerPerson: Double {

// calculate the total per person here

let peopleCount = Double(numberOfPeople + 1)

let tipSelection = Double(tipPercentages[tipPercentage])

let orderAmount = Double(checkAmount) ?? 0

let tipValue = orderAmount / 100 * tipSelection

let grandTotal = orderAmount + tipValue

let amountPerPerson = grandTotal / peopleCount

return amountPerPerson

}

var amountOfTip: Double {

let mealAmount = Double(checkAmount) ?? 0

let tipPicked = Double(tipPercentages[tipPercentage])

let tipTotal = Double(mealAmount / 100 * tipPicked)

return tipTotal

}

var mealCostWithTip: Double {

// calculate the total cost of the meal here

let tabAmount = Double(checkAmount) ?? 0

let tipSelected = Double(tipPercentages[tipPercentage])

let tipTotal = Double(tabAmount / 100 * tipSelected)

let totalTab = Double(tabAmount + tipTotal)

return totalTab

}

var body: some View {

UITableView.appearance().backgroundColor = .clear

return

NavigationView{

Form {

Section (header: Text("What is amount of check without the tip?").foregroundColor(.white)){

TextField("Amount", text: self.$checkAmount){

self.endEditing()

}// End TextField

.font(.callout)

.background(Color (.clear)).keyboardType(.decimalPad)

} // End Section

.font(.callout)

// Let the user pick the percentage of check for tip

Section (header: Text("How much tip do you want to leave?").foregroundColor(.white)){

// self.resumeEditing()

Picker("Tip percentage", selection: self.$tipPercentage){

ForEach(0 ..< self.tipPercentages.count) {

Text("\(self.tipPercentages[$0])%")

}

} // End Picker

} // End Section

.pickerStyle(SegmentedPickerStyle())

.font(.callout)

// Let user pick number of payors here

Section (header: Text("How many people are paying?").foregroundColor(.white)){

Picker("Number Paying", selection: self.$numberOfPeople) {

ForEach(0 ..< self.numPayees.count) {

Text("\(self.numPayees[$0])")

}

} // End Picker

} // End Section

.pickerStyle(SegmentedPickerStyle())

.font(.callout)

// Reveal tip amount

Section (header: Text("Amount of Tip").foregroundColor(.white)){

Text("$\(self.amountOfTip, specifier: "%.2f")")

} // End Section

.font(.callout)

// Reveal cost of meal with tip selected

Section (header: Text("Cost of Meal with Tip").foregroundColor(.white)){

Text("$\(self.mealCostWithTip, specifier: "%.2f")")

} // End Section

.font(.callout)

// Show the amount each person owes

Section (header: Text("Each Person Owes!").foregroundColor(.white)){

Text("$\(self.totalPerPerson, specifier: "%.2f")").bold()

.font(.title)

} // End Section

.font(.callout)

} // End Form

.navigationBarTitle("Split The Tab").background(Color (.blue)).edgesIgnoringSafeArea(.bottom)

} // End Navigation View

.onTapGesture {

self.endEditing()

}

} // End body View

private func endEditing() {

UIApplication.shared.endEditing()

}



/* private func resumeEditing() {

UIApplication.shared.resumeEditing()

} */

} // End ContentView





struct ContentView_Previews: PreviewProvider {

static var previews: some View {

ContentView()

}

}

Claude31,


I posted the ContentView that I'm having the issue with but it is being moderated. Hopefully, they'll get it to you soon.



Moderator:


Please get my last post to Claude31 so he can help. I've been beating my head against a wall with this issue for four or five days.


Thanks!


73 de Dale - K0HYD

If you post adding spaces in URL, like h ttps, that will go through directly, as there is no risk of activating the link directly.

Claude31,


Thank you for offering to help. I appreciate it. I'll send another reply with just a few snippets of the code and see if I can get it to you. I didn't have any URLs in the code. I just copied and pasted the entire ContentView View into the reply.


I experimented tonight moving the "onTapGesture" code around. and was able to make it work if I put it at the end of the section that has the TextField. But you have to tap on the header for that section to dismiss the keyboard. When I put it there, all of the Pickers worked.


I also tried putting the "onTapGesture" code at the end of the Form, at the end of the Navigation View. If I do that the keyboard will dismiss but neither of the Pickers will work.


I also tried putting in the BackgroundContent View and adding the "Background" to the main ContentView that is demonstrated in the stackflow.com example above. When I do this the I believe the keyboard dismissed but the Pickers did not work. This approach did not work at all.


My ContentView that is being moderated above has a Navigation View and in it is a Form View. The Form View contains a number of sections with Either TextField or Text Fields and Two Segmented Style Pickers.


I'll paste a couple of snippets in another Reply to see if I can get them to you.


Best Wishes for a Merry Christmas and Happy New Year. Enjoy your holidays. I really appreciate the help you have offered.


Dale - K0HYD

Claude31,


Here are a couple of Snippets. First is the First Section in the form which contains the TextField which uses the decimal keyboard:

Form {

Section (header: Text("What is amount of check without the tip?").foregroundColor(.white)){

TextField("Amount", text: self.$checkAmount){

self.endEditing()

}// End TextField

.font(.callout)

.background(Color (.clear)).keyboardType(.decimalPad)

} // End Section

.font(.callout)

//-------------

This Section is followed by two more Sections which contain Segmented PIckers.

// Let the user pick the percentage of check for tip

Section (header: Text("How much tip do you want to leave?").foregroundColor(.white)){

// self.resumeEditing()

Picker("Tip percentage", selection: self.$tipPercentage){

ForEach(0 ..< self.tipPercentages.count) {

Text("\(self.tipPercentages[$0])%")

}

} // End Picker

} // End Section

.pickerStyle(SegmentedPickerStyle())

.font(.callout)

//------------

The Second Picker Section is identical except it lets the user pick the number of people paying.


The "onTabGesture" code I'm using is:

.onTapGesture {

self.endEditing()

}

//------

As I said in my earlier reply, if I place it at the end of the first section I can release the keyboard by tapping up in the header area and all the Pickers work. But, it only works when tapping in the header area. If I tap in the Picker in the next Section for example, it will not release the keyboard.


I tried at the end of the Form, and at the end of the Navigation View. When I do this, the two Picker Sections do not function at all. You can tap on a value and nothing happens.


Thanks again for looking at these snippets. Hopefully they will get through and you will be able to read them.


Dale - K0HYD

SOLVED: I was able to get the keyboard to dismiss and the Picker Sections working at the same time by doing the following:


Use the code snippets provided by Claude31 at the top of this issue thread. Then:


1. Add this code to the ContentView.swift document immediately below the "import SwiftUI" line:


extension UIApplication {

func endEditing() {

sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)

}

}


2. Add this code immediately following the closing brace of the "body" block:


private func endEditing() {

UIApplication.shared.endEditing()

}


3. Insert this line of code in the TextField block:


TextField("Amount", text: self.$checkAmount){

self.endEditing() }


4. Modify the UIHostingController as window root view controller section of the SceneDelegate.swift document as follows:


// Use a UIHostingController as window root view controller.

if let windowScene = scene as? UIWindowScene {

let window = UIWindow(windowScene: windowScene)

window.rootViewController = UIHostingController(

rootView: contentView.onTapGesture(count: 2, perform: { window.endEditing(true)})

)

self.window = window

window.makeKeyAndVisible()

}


Note that in order for my background gradient to show through the Sections in the Form I need to add this code at the very top of the "body" View code block:


UITableView.appearance().backgroundColor = .clear

return


And add this modifier following the end of the TextField code block:


.background(Color (.clear))


These steps solved my issue. I hope I have provided enough detail to help anyone else who happens to run into these issues with the keyboard dismiss and the Pickers when they are used in a SwiftUI Form.


73

Dale - K0HYD

Thanks for the feedback.


Don't forget to close the thread.

Hey,

I have exactly the same problem but my TextField is in a subview of the ContentView (it's my SettingsView). Therefore I can't exactly use the code that was suggested for the SceneDelegate.swift - or can I? I would appreciate some help because it is bugging me that it has to be so hard to dismiss the number pad.

Thanks

How to dismiss keyboard after entering text in a textfield?
 
 
Q