I have an Text Field in my layout, which gets filled out, and afterwards when clicking on the UIButton in the layout, I want to hide the virtual keyboard.
I assume this can be done easily?
You can put below line in button click action.
self.view.endEditing(true)
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer =
UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
}
Use this Extension.
You can hide the Keyboard by tapping anywhere on the screen or just call dissmissKeyboard() to hide it.
text box means UITextView?
if it is UITextView then resignFirstResponder() is not allowed
you have to hide keyboards by clicking on background view
Related
I've added a label in a view controller via the interface builder, and I've added a lot of constraints to it, but I want to replace it by a button. Can I accomplish this without losing all the constraints ? Thanks a lot in advance
I'm not sure if you can save your constraints inside interface builder. However, you can add a tap gesture recognizer to make the label perform an action when it is tapped (act like a button).
This code can help you get started:
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap(_ :)))
myLabel.isUserInteractionEnabled = true
myLabel.addGestureRecognizer(tapGestureRecognizer)
func handleTap(_ sender: UITapGestureRecognizer) {
// perform some action when the label is tapped
}
You can look at this question for more information.
Don’t replace by button
Add tap gesture for click action
you don't need to remove that label. Just addGestureRecognizer a tap gesture on label.
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap(_ :)))
myLabel.isUserInteractionEnabled = true
myLabel.addGestureRecognizer(tapGestureRecognizer)
func handleTap(_ sender: UITapGestureRecognizer) {
// perform some action when the label is tapped
}
My tricky problem is :
I've 2 buttons with 2 UITextView.
Like you know, when I push an UITextView, keyboard appear. Well, this is not what I want.
I want to enable / disable the display's keyboard according a specific #IBAction taped.
The scenario is the following:
- First button (Keyboard icon) allow the user to display the keyboard to type something in one of the UITextView, with a FirstResponder init on the top one.
Second button (REC icon) allow the user to speak and display in pre-selected TextView but without displaying keyboard.
I already known that there is :
isUserInteractionEnabled
and
textViewDidBeginEditing
But it doesn't really fit well and/or fix my issue.
Here a screen to be more explicit (don't give a mind about the third green validate button, it's just for the .POST feature) :
Thanks for any help!
If I understand your problem correctly, You don't want the keyboard to appear when user taps on the textField but rather should come up only when user taps on Keyboard button and should dismiss on tapping other button.
All the posted answers mostly focus only on second part of showing keyboard and dismissing them on tapping button. Whats more tricky is preventing keyboard from appearing in when user taps on textField :)
Possible solutions you can try and their cons:
Solution 1:
Try setting textfield isEnabled = false sure this will prevent keyboard from appearing when user taps on textField but guess what Keyboard will not appear even on calling textfield.becomeFirstResponder() ahhh trouble :)
Solution 2:
implementing textFieldShouldBeginEditing of UITextField delegate and returing true or false based on whether used tapped on button or textField itself.
Sure it works but you will need to figure out way to tell textFieldShouldBeginEditing why was it triggered because of button or because of touch on textField again complications.
My Solution:
Use 2 textFields. One disable user interaction forever and use another textField which will never appear to user but will take care of showing keyboard when required.
Enough talk lets code :)
Step 1:
Lets say your textField which appears on screen is called textField
textfield.isEnabled = false
This will ensure whatever you do keyboard will not appear for this keyboard.
Step 2:
Create a temp textField of frame zero (which user can never tap :P )
tempTextField = UITextField(frame: CGRect.zero)
tempTextField.delegate = self
self.view.addSubview(tempTextField)
Step 3:
Now when user taps on show keyboard button, make your temp textField first responder
tempTextField.becomeFirstResponder()
and when user taps on other button resignFirstResponder for tempTextField.
tempTextField.resignFirstResponder()
Step 4:
But wait when user types nothing appears on my textField. Wait simply implement
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == tempTextField {
self.textfield.text = (self.textfield.text ?? "") + string
}
return true
}
EDIT:
You don't really need two textFields, you can achieve the same with a UILabel and UITextField as well. I chose UITextField as I am not sure what are other requirements of yours!
Problem fixed. Hope it helps :)
Something like this should work:
class MyViewController: UIViewController, UITextViewDelegate {
#IBOutlet var yourTextView: UITextView
override func viewDidLoad() {
super.viewDidLoad()
yourTextView.delegate = self
}
#IBAction func showKeyboard(_ sender: UIButton) {
self.yourTextView.becomeFirstResponder()
}
#IBAction func hideKeyboard(_ sender: UIButton) {
self.yourTextView.resignFirstResponder()
}
}
You say
But it's not really working in my case.
Why?
You can disable the textfields interaction with (swift 3):
textField.isUserInteractionEnabled = false
Next, when you click on the keyboard button you can reenable the interaction so when the user click on one of the textfield the keyboard opens.
On the keyboard dismiss (you can see the UIKeyboardWillHideNotification callback notification) you can set the interaction to false.
function to dismiss KeyBoard when button is clicked:
#IBAction func hideKeyboard() {
textView.resignFirstResponder()
}
function to get keyboard to show up:
#IBAction func showKeyboard() {
textView.becomeFirstResponder()
}
Just copy and paste simple code for you accessory button embedded with keypad
func addKeyboardToolbar() {
let ViewForDoneButtonOnKeyboard = UIToolbar()
ViewForDoneButtonOnKeyboard.sizeToFit()
let button = UIButton.init(type: .custom)
button.setImage(UIImage.init(named: "login-logo"), for: UIControlState.normal)
button.addTarget(self, action:#selector(doneBtnfromKeyboardClicked), for:.touchUpInside)
button.frame = CGRect.init(x: 0, y: 0, width:UIScreen.main.bounds.width, height: 30) //CGRectMake(0, 0, 30, 30)
let barButton = UIBarButtonItem.init(customView: button)
ViewForDoneButtonOnKeyboard.items = [barButton]
postTextView.inputAccessoryView = ViewForDoneButtonOnKeyboard
}
#IBAction func doneBtnfromKeyboardClicked (sender: Any) {
self.contentView.endEditing(true)
}
my problem is the following, I don't know if is a bug or if I'm doing something wrong. The thing is that I have a view as shown below, and have two text field (the third one was for testing purposes), but I only can see the text if I have the UITextField focused, once I tap anywhere else but the TextFields view.endEditing(true) is executed. and then the text is not gone, but not visible either. There is text in the second and third textField. ¿Any ideas?
UPDATE: Added code for better comprenhension.
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(patternImage: UIImage(named: "fondo_nadserv")!)
otroDatoField.delegate = self
datoField.delegate = self
//Looks for single or multiple taps.
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "DismissKeyboard")
view.addGestureRecognizer(tap)
}
//Calls this function when the tap is recognized.
func DismissKeyboard(){
view.endEditing(true)
}}
I'm a noob here and in iOS world. I am having trouble dismiss keyboard on a specific case in my very simple todo list iOS app.
I'd like the keyboard to get dismiss when user taps anywhere outside the current text field or the keyboard itself. So far, I got the keyboard dismisses just fine (thanks to you guys here in stack overflow) when user taps on the UITableView, or most element on my app. HOWEVER, when user taps on another UITextField, the keyboard does not go away.
FYI, here's the list of existing threads I researched so far but have yet to solve this issue.
1) How to dismiss keyboard iOS programmatically
2) Resigning First Responder for multiple UITextFields
3) Dismissing the First Responder/Keyboard with multiple Textfields
4) (a few more at least but I lost track :( )
Here's what I did so far:
(in viewDidLoad())
// Add 'tap' gesture to dismiss keyboard when done adding/editing to-do item
var tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapOutside:")
tap.cancelsTouchesInView = true
self.view.addGestureRecognizer(tap)
func tapOutside(tapOutside: UIGestureRecognizer) {
// Dismiss keyboard
self.view.endEditing(true)
}
#IBAction func EditingDidBegin(sender: UITextField) {
// Highlight the text field which user is editing
self.highlightTextField(sender, highlight: true)
}
#IBAction func EditingDidEnd(sender: UITextField) {
// Undo text field highlight
self.highlightTextField(sender, highlight: false)
self.view.endEditing(true) // try this option and not working
self.setEditing(false, animated: true) // try this option and not working
sender.resignFirstResponder() // try this option and not working
UIApplication.sharedApplication().becomeFirstResponder() // try this option and not working
... // below is my code to update the todo item
}
I also tried to print out all subviews.isFirstResponder() of my view. All of it return false. I also tried override touchesBegan of my UIViewController, and inside it just calls self.view.endEditing(true) and call its super's. This also does not work.
Please help. :(
TIA!
UPDATE:
You guys are awesome! :D I got it working now thanks to you guys. There were several mistakes / messed up as I'm learning new framework. So here's what I did.
1) I did not set UITextField delegate correctly.
Mistake: I ctrl-draged textfield in xcode and link my viewController as delegate and thought that should work out. I will still need to research and understand better why.
Solution: I removed that ctrl-drag link and explicitly call myTextField.delegate = self in tableView:cellForRowAtIndexPath. And that did it. Thanks #Sidewalker
2) Mistake: I have a mixed of textFieldShouldBeginEditing, etc. and #IBAction func EditingDidBegin. So I got myself into the situation where textFieldShouldBeginEditing got the call, but EditingDidBegin did not get call.
Solution: Once I set the delegate = self explicitly and stick with implementing textField... methods and not use any #IBAction for textField, things just work.
Here's one option... We're going to add a boolean flag to determine whether or not we're in a textField when an edit attempt for another textField begins
Make your class adhere to UITextFieldDelegate
class MyClass: UIViewController, UITextFieldDelegate
Don't forget to set the delegate, we'll add the flag as well
myTextField.delegate = self
var inField = false
Implement "textFieldShouldBeginEditing" and "textFieldDidBeginEditing"
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if inField {
inField = false
return false
}
return true
}
func textFieldDidBeginEditing(textField: UITextField) {
inField = true
}
I prefer tracking things like this rather than identifying subviews as it allows the flag to be utilized elsewhere and cuts down code complexity.
Well the keyboard isn't going away because it doesn't expect to have to. The new UITextField is just becoming the first responder while the other resigns. If you don't want a textField to become the first responder if another is already, you're going to have to cut it off before it gets the chance to. I would try to implement textFieldShouldBeginEditing and figuring out the logic there.
I'm not in love with the way this looks but this should do something along those lines.
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
for subView in self.view.subviews{
if(subView.isKindOfClass(UITextField)){
if(subView.isFirstResponder()){
subView.resignFirstResponder();
return false;
}
}
}
return true;
}
First set all the UITextField (your are creating) delegate as self and create one UITextField member variable. Now implement "textFieldDidBeginEditing" delegate method and assign the textfield to your member UITextField variable. As given below
func textFieldDidBeginEditing(textField: UITextField) {
yourMemberVariable = textField;
}
So now whenever you want to dismiss the keyboard call the dismiss method on "yourMemberVariable" object. It should work !!
What I usually do is implementing this two method:
The first one add a UITapGestureRecognizer to the whole UIViewController view
func hideKeyboard() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
view.addGestureRecognizer(tap)
}
The second one just get called every time the user touch anywhere on the UIViewController's view
func dismissKeyboard() {
self.view.resignFirstResponder()
}
I add the first one to the viewDidLoad method of the UIViewController. Or better yet if you want to use that on all the app just make that an extension for your UIViewController.
How about doing this in viewController, It works for me
func dismissKeyboard() {
//All the textFields in the form
let textFields = [textField1, textField2, textField3, textField4, textField5]
let firstResponder = textFields.first(where: {$0.isFirstResponder ?? false })
firstResponder?.resignFirstResponder()
}
How would you dismiss the keyboard from the UITextField when tapping outside of the keyboard. I have tried resignFirstResponder() and it only exits after typing one number. I have also tried textField.inputView = UIView.frame(frame: CGRectZero). I have seen many Obj-C verisons of what I'm asking but I need the Swift equivalent because I have no programming experience in Objective-C
Thank you for your time and patience.
The best way to add a tap gesture recognizer to the view and calling either resignFirstResponder() or self.view.endEditing(true). I prefer endEditing() since resignFirstResponder has to be done for each text field separately unlike endEditing which is done for the view itself.
In viewDidLoad, write the below code:
let tapRecognizer = UITapGestureRecognizer()
tapRecognizer.addTarget(self, action: "didTapView")
self.view.addGestureRecognizer(tapRecognizer)
Now write the didTapView method to dismiss the keyboard:
func didTapView(){
self.view.endEditing(true)
}
Now when you tap outside the keyboard on the main view of the controller, it will call the didTapView method and dismiss the keyboard.
Swift 3.x
The code in viewDidLoad should be:
let tapRecognizer = UITapGestureRecognizer()
tapRecognizer.addTarget(self, action: #selector(ViewController.didTapView))
self.view.addGestureRecognizer(tapRecognizer)
where ViewController should be the name of your view controller.
Thanks
Swift 3 tested and working
// dismiss keyboard on touch outside textfield
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for txt in self.view.subviews {
if txt.isKind(of: UITextField.self) && txt.isFirstResponder {
txt.resignFirstResponder()
}
}
}
Enjoy
Swift 2.3 tested and working
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for txt in self.view.subviews {
if txt.isKindOfClass(UITextField.self) && txt.isFirstResponder() {
txt.resignFirstResponder()
}
}
}
Enjoy
You could also use this method to dismiss the keyboard when pressing 'Return'
func textFieldShouldReturn(textField: UITextField!) -> Bool {
self.view.endEditing(true);
return false;
}
Make sure to set your delegate
If you don't want to define an extra method, there is a slightly simpler way that will also work
let tapRecognizer = UITapGestureRecognizer(target: self, action: "endEditing:")
view.addGestureRecognizer(tapRecognizer)
I found this code on a site and it works great for me!
//FUNCTION TO DISMISS THE KEYBOARD
func initializeHideKeyboard(){
//Declare a Tap Gesture Recognizer which will trigger our dismissMyKeyboard() function
let tap: UITapGestureRecognizer = UITapGestureRecognizer(
target: self,
action: #selector(dismissMyKeyboard))
//Add this tap gesture recognizer to the parent view
view.addGestureRecognizer(tap)
}
#objc func dismissMyKeyboard(){
//endEditing causes the view (or one of its embedded text fields) to resign the first responder status.
//In short- Dismiss the active keyboard.
view.endEditing(true)
}
Then just call this function in a button action or similar:
dismissMyKeyboard()