How to remove focus from UITextField? - ios

I have seen this question asked million times everywhere, but there's no single answer that has been working for me.
I need to remove focus from a UITextField. That means I need the cursor to go away (and the keyboard dismissed).
The solution I've seen on the internet is either [textfield resignFirstResponder] or [textfield endEditing:YES], which is able to hide the keyboard, but does not remove focus from UITextField (i.e. the cursor still blinking happily inside the UITextField, although the keyboard is dismissed).
The thing with this is I need to get event when the user tap into the UITextField and the event didBeginEditing is fired. I'm doing something each time that event is fired, or more generally, each time the user tap on the UITextField. But if the focus isn't removed entirely from the UITextField, the event can't be fired again even after I called resignFirstResponder or endEditing:YES.
How can I achieve this? Thanks.

you can make the cusor color as clear color
textfeild.tintColor = UIColor.clearColor()
if you just want to dismiss the keyboard then
textfeild.resignFirstResponder()
will dismiss the keyboard and when you want focus again use
textfeild.becomeFirstResponder()

I had the same problem ages ago.
I had a screen containing a UITextField, and some other controls, some of which were appearing under the onscreen keyboard (yes, I know now I should've used constraints to make sure the onscreen UIView fitted the visible part of the screen).
The problem in my case was that on a Modal screen, once the onscreen keyboard appears, you can never get rid of it, even if you try using resignFirstResponder. In its wisdom, Apple has deliberately designed it this way, to stop the user being annoyed by the keyboard appearing, and disappearing. Uh-huh.
My solution was simple:
Make your UITextField disabled. Even if it's just for a fraction of a second, then you re-enable it.
This'll make the onscreen keyboard nicely slide away.

If you just need to detect when the textfield is touched and not specifically the didBeginEditing, why not just make a subclass of UITextField and override touchesBegan like so
class SpecialTextField: UITextField {
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
print("touched textfield")
}
}
then you can use that to fire your event via a delegate method, or directly somehow

If someone is still facing the issue, the cursor remains if resignFirstResponder() is not called from main queue.
So you just need to:
DispatchQueue.main.async {
textView.resignFirstResponder()
}

Related

IQKeboard manager leaving lot of top space when going to previous textfield

I have list of textfields inside stackviews which are again embedded in scrollview. For keyboard handling I've used IQKeyboard manager it works fine. Although there is a special case when it leaves too much space on top. Below is my current UI structure
Now suppose my cursor is on second textfield and I scrolled up till the end, now if I tap on the previous button, the focus does comes on first textfield but it also scrolls it down to show it just above keyboard like below screenshot. My actual expectation is, it should focus on first textfield like now but it should keep the top space to come down constant and shouldn't leave this much space.
From codewise I just enabled the IQKeyboardManager from AppDelegate. No other code is added for this.
IQKeyboardManager.shared.enable = true
Any help is appreciated
Try updating scroll view content offset on textFieldDidEndEditing like below
func textFieldDidEndEditing(_ textField: UITextField) {
scrollview.setContentOffset(CGPoint.zero, animated: false)
}

How to manually show/stop keyboard in UITextView textViewDidBeginEditing

In textViewDidBeginEditing I'm doing some check to show Alert. My problem is that both Keyboard and Alert show up same time. I don't want keyboard to show when alert is shown. Is it possible to stop keyboard showing up inside textViewDidBeginEditing when I've to show Alert and once alert is dismissed revert it back to normal?
If not how do we achieve it via any other workaround?
Set the UITextView's isEditable property to false.
Detect for taps on the UITextView (that's what a user will do if he wants to start editing) possibly using a UITapGestureRecognizer and check if the tap coordinates lie within the frame of the UITextView.
At this time, the keyboard will not show. You can make the check you need, and based upon whether the check passes or fails, you can make the keyboard show (set UITextView's isEditbale to true and make it the firstResponder).
Once the user has finished editing, reset the state if you want to repeat the similar action.
Call view.endEditing(true) function in textViewDidBeginEditing and keyboard didn't show. I think it's will work.

iOS Custom keyboard can't return focus to app's textfield

I'm working on a custom keyboard for iOS which will have its own search field (similarly implemented by PopKey).
My keyboard's textfield is able to take the focus with becomeFirstResponder and I'm able to give it up by using resignFirstResponder. However after I resign focus, the host app has a difficult time retaking focus despite touching the form. The app's textfield will still show the text cursor blinking.
Any ideas? Thanks
The solution is a hack, as of right now you can't really give the host app its focus back.
Subclass a UITextField and on its delegate implement
textFieldShouldBeginEditing by returning NO.
Add a BOOL property isSelected that gets set to YES in touchesBegan (not to be confused with the default selected property)
In your keyboard's keyPressed method, if searchField.isSelected, manipulate the searchField.text. Else, manipulate textDocumentProxy like normal.
Add a clear button and method that wipes searchField.text and searchField.isSelected, allowing any further keystrokes to return to the textDocumentProxy
Add an animation that replicates the blinking type cursor

Touch Down/Up and Scroll in UITableViewController

I'm having a bit of of a pain point in figuring something out.
I have a uitableviewcontroller, and each cell is static. Inside each cell is a textbox. When the user TAPS on a textbox, I'd like an event to fire.
So while I'd like my table to still scroll, i'd also like tap events to work when you tape the textbox.
Apparently in uitableviews, they add a delay to your tap so you have to hold your finger down for a second or so for 'tap' to register. I felt this was not intuitive to a user, so I did this to fix it:
for subview in self.tableView.subviews as [UIView]
{
if subview is UIScrollView
{
let scroll = subview as UIScrollView
scroll.delaysContentTouches = false
break
}
}
This works perfectly, and now when I tap my textbox, it instantly executes my tap event! The problem now, however, is some of my textboxes are positioned right where a user would naturally scroll. When they put their finger down (touch down event) to scroll, it's unfortunately being intercepted by the tap event, and prevents scrolling and instead executes my event.
What i'd really want is if the user puts their finger down, and then swipes, it doesn't execute the touch down event. I thought to be clever and switch touch down to touch up, but when I put my finger down and then pick it back up, it does nothing (touch up inside seems to do nothing). I read this was because it only works on buttons and things like that, and not textfields. So, yes, now I can scroll without my action, but when I tap the textbox and lift my finger up it doesn't execute that, either.
Any ideas on how to either
1) permit touch downs and scrolling to co-exist without having to hold my finger down for a second and deal with that delayContentTouches?
2) somehow get a tap up inside event to fire when I tap on a textbox?
I saw some info here but didn't seem to help much:
UIButton inside UITableViewCell steals touch from UITableView
Thanks!
Well, as luck would have it, I was able to figure this out. Would love some criticism/advice if something might not be ideal here, but what I did was add this to my subclassed textfield:
override func canBecomeFirstResponder() -> Bool {
performMyFunctionHere()
return false
}
So I am returning false on first responder which prevents any sort of keyboard appearing (which is what I wanted) and instead using performMyFunctionHere() I can do what I wanted to do (in my case, make an action sheet picker appear). I assign the action sheet picker in my view controller and assign it to each specific instance of my subclassed uitextfield. Nothing really complicated, to be honest. I'm surprised this works as well as it does.
By the way one thing that didn't seem extremely important was setting the delaysContentTouches as I mentioned above. I guess because now it's using the responder it will always work? It didn't seem to matter whether I removed it or not, but would love thoughts on whether it's better to leave it in or not.
Thanks!

Is there a way to know that iOS keyboard is really hidden (dismissed by user)?

I need a way to detect the case when user dismisses iOS keyboard manually, using "keyboard" button on keyboard. I tried to use UIKeyboardDidHideNotification, but quickly discovered that this event is also fired when user splits the keyboard, leaving it on screen.
Is there a way to know for sure that keyboard was really hidden?
To get solution I had to slightly modify my original implementation: I've replaced assigning nil to inputView member of my main view with creating and destroying custom invisible UIView<UIKeyInput> view to show and hide keyboard correspondingly. This allowed me to override this view's resignFirstResponder method which is always called on keyboard resigning - either in normal or in split state, when user dismisses keyboard using special button or when I remove it programmatically.
I believe that UIKeyboardDidHideNotification is only sent when the keyboard is truly gone. From the Apple docs:
Posted immediately after the dismissal of the keyboard.
However, you could also look to see if any of your inputs are currently the first responder:
BOOL keyboardUp = NO;
for (UIView *view in self.textInputs)
{
if (view.isFirstResponder)
{
keyboardUp = YES;
break;
}
}

Resources