Swift 4 - How to enable / disable keyboard by using buttons - ios

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)
}

Related

Swift textfield select all text on click

I am using swift in a storyboad application, and I would like it to, when a user enters the box (IE, when it becomes the first responder) to enter text it highlights all the text. What is done in most web browsers. Here is what I have tried, which has not worked:
func textFieldDidBeginEditing(_ textField: UITextField) {
// textField.selectAll(nil)
print("click 2")
// textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.endOfDocument)
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
print("click 1")
// textField.selectAll(nil)
// textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.endOfDocument)
return true
}
Making a button that runs this code does actually work, but I want it to be when you click on the field. Making an invisible button on top seems like a bad idea. I've tried other variations of this as well, but none have worked for me.
UPDATE: What I've ended up doing was making an invisible button on top of the existing text field, and then making that select the text. It may be a little janky but it works perfectly so I have no problems with that solution anymore. Extra code:
#IBAction func seachBtnClicked(_ sender: Any) {
//The invisible button over the search bar has been clicked
search.selectAll(nil)
searchBtn.isHidden = true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
//Return has been pressed, so we are going to load a new page
processInput()
//This does mean that it only comes back if you press enter,
//but right now I think that's how I want it.
//Could change it to be in the textFieldDidEndEditing() function to change that
searchBtn.isHidden = false
return true
}
You are probably just missing the textField.delegate = self for your textfield. The first of the two functions, func textFieldDidBeginEditing(_ textField: UITextField) is the one that is always performed as soon as a textfield is tapped on to focus on it.
Try adding yourTextField.delegate = self in your viewDidLoad function and see if that works out.
What I've ended up doing was making an invisible button on top of the existing text field, and then making that select the text. It may be a little janky but it works perfectly so I have no problems with that solution anymore. Extra code:
#IBAction func seachBtnClicked(_ sender: Any) {
//The invisible button over the search bar has been clicked
search.selectAll(nil)
searchBtn.isHidden = true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
//Return has been pressed, so we are going to load a new page
processInput()
//This does mean that it only comes back if you press enter,
//but right now I think that's how I want it.
//Could change it to be in the textFieldDidEndEditing() function to change that
searchBtn.isHidden = false
return true
}

Hide the IOS Keyboard

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

Open view when tapping the text field without opening the keyboard [duplicate]

This question already has answers here:
Disable UITextField keyboard?
(10 answers)
Closed 4 years ago.
I am developing an app in which I want to open a view when the user clicks on a text field but I don't want to open the keyboard. How can I achieve this?
You can easily achieve it by setting an empty custom input view to the textField:
textField.inputView = UIView(frame: CGRect.zero)
Then the textField can become first responder normally, but this view (with zero frame) will be presented instead of the keyboard.
Set your ViewController as your TextFields delegate using
self.yourTextfield.delegate = self
and now implement the UITextFieldDelegate as shown below
extension ViewController : UITextFieldDelegate {
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
//Load your VC here
return false
}
}
Thats all :) Hope it helps
You can use below textField Delegate Method
func textFieldDidBeginEditing(_ textField: UITextField) {
yourTextField.resignFirstResponder()
//code for show view
}
Hope it will help!
You can simply add a tap gesture recognizer to the text field.
let tapGestRec = UITapGestureRecognizer(target: self, action: #selector(textFieldTapped))
textField.addGestureRecognizer(tapGestRec)

Hiding a UIButton when a text field is clicked on Swift

New to Swift and making a simple to-do app.
I am trying to get it so that when a UI TextField is clicked on, a certain button should be hidden. It's only when the user presses enter after typing in a task that the button should appear.
I have an IBAction set up for my text field to hide the UIButton when it is clicked on like so, but it doesn't work:
#IBAction func textFieldClicked(_ sender: Any) {
self.cellButton.isHidden = true
}
And I have set up my textfieldshouldreturn function when the user presses enter like so:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.cellButton.isHidden = false
self.cellButton.isUserInteractionEnabled = true
textField.resignFirstResponder()
return true
}
Does an IBAction for text field only respond when enter is pressed? I tried messing with flags but that didn't work either.
Any help is appreciated.
You don't need an IBAction for this. Instead, implement another UITextFieldDelegate method - textFieldDidBeginEditing.
func textFieldDidBeginEditing(_ textField: UITextField) {
self.cellButton.isHidden = true
}
This delegate is called when a text field becomes the first responder.
On a slightly unrelated note, it's best to return false instead of true from your textFieldShouldReturn method.
Please, use delegates method textFieldDidDeginEditing and hide button.

How to dismiss keyboard with multiple UITextField

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()
}

Resources