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)
}
Related
I've been doing iOS development for a long time and I've never run into this before. The UITextField appears in the UI, it is correctly sized and placed by the constraints I've given it, but when I tap/click on it and doesn't respond. The cursor doesn't appear in the field and the keyboard doesn't show up.
let textfield = UITextField()
textfield.translatesAutoresizingMaskIntoConstraints = false
self.contentview.addSubview(textfield)
textfield.keyboardType = .numberPad
textfield.borderStyle = .roundedRect
textfield.text = "stuff"
// and then I set up constraints which are working as expected
I've double checked my simulator to make sure it isn't a soft keyboard issue.
I don't need any specialized UITextFieldDelegate behavior, I just need to standard behavior that tapping will cause it to become first responder, set the cursor there, and open the keyboard. When I add a UITextField via a storyboard, I don't need to set a delegate in order to get this behavior, so I can't imagine I would need to create specialized delegate code in order to get this basic behavior.
Just to test if something else was wrong, I've tried programmatically forcing the textfield to become first responder and that works.
I've tried forcing this to be true, just in case:
textfield.isUserInteractionEnabled = true
but that didn't change anything.
Any ideas? Why isn't my programmatically created UITextField accepting taps?
EDIT: Got an excellent suggestion to check out the Hierarchy Inspector to see if anything else is on top of it. It looks like I don't have anything on top of it: Here's a screenshot of the sim and of the hierarchy inspector turned a bit to the side so you can see the layers.
There isn't anything in front of the UITextField. (The UITextField has like 4 internal layers, but nothing is in front of them.)
As we have discussed in the comments under the OP, it's always a good idea to check the view hierarchy in the View Hierarchy Inspector to see if the frame is laid out properly and also if perhaps some other view isn't covering the other view which should become the first responder.
The view hierarchy inspector can be found here once the app is running on a simulator or a device.
UIKit. For example, I have five textfields in my app. All in one ViewController. When I launch my app all these textfields appears simultaneously on the view.
So, I would like to make next changes:
Launching App -> User sees first textfield -> Tap on it, enter info -> tap something (like button or just finish editing first textfield, doesn't matter) ->
Second textfield appears on the view, after the first textfield. <..> ->
Third textfield appears on the view <..> ->
Fourth textfield appears on the view. <..> ->
Fifth textfield appears on the view.
Plus I would like to use animation to get the smooth appearing effect (it's a different story, meantime).
Could you help me, please?
Add the textfield to a UIStackView.
Hide all but the first textfields using isHidden = true
Set the view controller to be the delegate of all text fields.
Override one of the relevant delegate methods to get notified when editing finishes. Which one depends on what you want to do and when editing finishes.
Set isHidden = false for the text field that should appear within an animation block. Use UIView-based animation or UIViewPropertyAnimator.
If one of the points is unclear, you are not ready yet to build this. Read, read and experiment until these points become clear. Then implement them.
I'm a new programmer that's still learning, so forgive me if my code looks like crap. I'm writing a program that has a ViewController called "infoViewController" with multiple UITextFields on it. The user is supposed to fill out the textfields and then click the "Next" button in the upper-right of the screen, which then activates a "Show" segue and takes them to the next VC. All the info from the Text Fields are stored in constants for later down the road when I take that information that they inputted and place it on a .PDF file that is generated at the end. I wanted the user to be able to easily go through the text fields, so I made it where when the user is on the TextField and clicks "Next" on their keyboard, it moves them to the next TextField so that they can fill them all out quickly and easily. The issue I run into is that for some reason I keep getting this error when I click "Next" on the keyboard:
[Snapshotting] Snapshotting a view (0x7f89955786c0, _UIReplicantView) that has not been rendered at least once requires afterScreenUpdates:YES.
The app still works... but I'd rather not have an error showing up in the panel (in Xcode) at all lol. Also, when it does this, it's like the screen glitches and flickers white for a split second (super fast) before it moves on to the next TextField... any solutions?
Please dumb anything you reply down to a beginners level. Thanks!
Here's the code I wrote for switching between TextFields:
extension infoViewController {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let nextTag = textField.tag + 1
if let nextResponder = textField.superview?.viewWithTag(nextTag) {
nextResponder.becomeFirstResponder()
} else {
textField.resignFirstResponder()
}
return true
}
}
I assigned the TextField delegates in "viewDidLoad."
(Ex: clientTextField.delegate = self)
I also assigned the tags in "viewDidLoad."
(Ex: clientTextField.tag = 0)
I had the same warning whenever a textField switched firstResponders. But this only happened for textFields that had the Text Input Trait of Capitalization set to anything other than None.
Text Input Traits can be found in the Attributes Inspector under Min Font Size.
In my case, changing Text Input Trait of Capitalization to None removed that warning. While this worked for me, I imagine this only solves a symptom, not the underlying problem.
I would say, wrap your call to
nextResponder.becomeFirstResponder()
And also your call to
textField.resignFirstResponder
In a very brief delay to let the function return before you play with the first responder.
On apps like say the stock messages app, if you’re in a conversation with the keyboard showing and swipe to go back to your conversation list, the keyboard remains up as the view gets swiped away.
I can’t seem to figure out how to mimic this behavior but I’ve seen it in other apps so it’s gotta be possible.
Edit: Not sure I understand why this is getting downvotes. It’s definitely a valid question where I couldn’t find the answer on google?
Edit 2: Here’s a video of what I’m trying to accomplish https://arxius.io/v/a555c8db compared to this behavior in discord https://arxius.io/v/0bfda09a
On apps like say the stock messages app, if you’re in a conversation with the keyboard showing and swipe to go back to your conversation list, the keyboard remains up as the view gets swiped away.
I don't actually see that behavior, at least in the Messages app on an iPhone. That said, the keyboard should remain visible whenever the first responder can accept text. If you want to switch to a different view controller and keep the keyboard visible, then make sure that first responder in the new view graph is editable. For example, if there's a text field, you could set it to be the first responder.
So before we talk about any kind of solution, let's learn exactly why the keyboard is dismissed.
As you know, iOS UI works on a view controller based system, with a text field ultimately being managed by a view controller somewhere.
When you click the back button, the active view controller is released from the navigation stack and therefore the system deduces that the text field is no longer in use, so it resigns it as the first responder.
Unfortunately there is no built in way to alter this behaviour and whilst we can speculate how apple might do it, we do not know.
The few options we have are not particularly neat or tidy, but a method I have had success with in the past is creating a hidden text field directly on the window before you pop the view controller and setting it first responder. Then on your other view controller, the text field can take first responder from the invisible one and remove it.
This is not ideal, but it's the only technique that comes to mind.
It is correct that you had to have UITextFiled available for both views to have keyboard passed between them consistently. But nobody said that this textfield had to be on screen, or had to be part of ViewController's view.
So all you had to do is to place this textFiled somewhere out of screen, for example as subview of your window, or NavigationController's view, make it first responder, and switch to your text field on view didAppear:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.textField.becomeFirstResponder()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
let fixedView = self.view.window
let fakeTextField = fixedView?.subviews.last as? UITextField ?? UITextField()
fakeTextField.autocapitalizationType = textField.autocapitalizationType
fakeTextField.autocorrectionType = textField.autocorrectionType
fakeTextField.center = CGPoint(x: -100, y: -100)
fixedView?.addSubview(fakeTextField)
fakeTextField.becomeFirstResponder()
}
Make sure that keyboard configuration is the same, otherwise you will have it switching.
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()
}