Description
I have a few UITextField which I want to scroll up, when one of them is covered by keyboard during edition. There are a tons of answers here on SO with many flavors: moving a view (by changing its frame), modifying a constraint, using UIScrollView and UITableView, or using UIScrollView and modifying contentInset.
I decided to use the last one. This one is also described by Apple, and has a Swift version on SO as well as being described on this blog including a sample project on the GitHub.
Partial code
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(textField: UITextField) {
self.activeField = nil
}
func textFieldDidBeginEditing(textField: UITextField) {
self.activeField = textField
}
func keyboardWillShow(notification: NSNotification) {
if let activeField = self.activeField, keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize.height, right: 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect = self.view.frame
aRect.size.height -= keyboardSize.size.height
if (!CGRectContainsPoint(aRect, activeField.frame.origin)) {
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
func keyboardWillBeHidden(notification: NSNotification) {
let contentInsets = UIEdgeInsetsZero
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
}
Issue
I want just one simple modification - a little more space between the keyboard and an edited field. Because out of the box it looks like this:
I modified CGRect
in scrollRectToVisible
call, but it changed nothing. What's more, even commenting out the line with scrollRectToVisible
had no effect at all - everything worked exactly as before (including scrolling up the content). Checked on iOS 9.2
Replicating, if needed, is trivial - just download the working code using the GitHub link above and comment out the scrollRectToVisible line.
Tested workarounds
Workarounds I tried, but didn't like the final effect:
- Increasing
contentInset
- user could scroll up more then the contentSize - Replacing
UIKeyboardDidShowNotification
withUIKeyboardWillShowNotification
, add anotherUIKeyboardDidShowNotification
observer with justscrollRectToVisible
inside - it works, but then there are two scroll up animations, which doesn't look good.
Questions
- Why changing
contentInset
(withoutscrollRectToVisible
call) scrolls content in the scrollView? I've not see in any docs information about such behavior - And more important - what to do, to scroll it up a little more, to have some space between an edited text field and the keyboard?
What did I miss? Is there some easy way to fix it? Or maybe it's better to play with scrollView.contentSize
, instead of contentInset
?