I've searched all over S.O. for a simple solution to get the cursor's current position, then scroll to it (assuming the keyboard is visible). Most seem overly complicated and/or ineffective in certain situations. How can I make scrolling work every time, whether the cursor is below a keyboard or not?
1) Be sure your UITextView
's contentInset
s are properly set & your textView
is already firstResponder
before doing this. The contentInset
property tells the textView
where the visible area is for the user. If the keyboard is visible, be sure the textView.contentInset.bottom
property has been set to the top border of the keyboard otherwise the textView
may scroll to a space not visible, behind the keyboard.
See this S.O. post for more information: What's the UIScrollView contentInset property for?
2) After my the insets are ready to go, and the textView
is firstResponder
, I call the following function:
private func scrollToCursorPositionIfBelowKeyboard() {
let caret = textView.caretRectForPosition(textView.selectedTextRange!.start)
let keyboardTopBorder = textView.bounds.size.height - keyboardHeight!
// Remember, the y-scale starts in the upper-left hand corner at "0", then gets
// larger as you go down the screen from top-to-bottom. Therefore, the caret.origin.y
// being larger than keyboardTopBorder indicates that the caret sits below the
// keyboardTopBorder, and the textView needs to scroll to the position.
if caret.origin.y > keyboardTopBorder {
textView.scrollRectToVisible(caret, animated: true)
}
}
Optional: If you just want to scroll to the cursor's current position (assuming the textView
is currently firstResponder
and contentInset
has been properly set before now), just call:
private func scrollToCursorPosition() {
let caret = textView.caretRectForPosition(textView.selectedTextRange!.start)
textView.scrollRectToVisible(caret, animated: true)
}
Extra Information: In order to set the textView
scroll bars to the proper height, modify the scrollIndicatorInsets
by doing something like:
// This is not relative to the coordinate plane. You simply set the `.bottom` property
// as if it were a normal height property. The textView does the rest for you.
textView.contentInset.bottom = keyboardHeight
textView.scrollIndicatorInsets = textView.contentInset // Matches textView's visible space.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With