UITextView in iOS7 clips the last line of text string
The problem is due to iOS 7. In the text view delegate, add this code:
- (void)textViewDidChange:(UITextView *)textView {
CGRect line = [textView caretRectForPosition:
textView.selectedTextRange.start];
CGFloat overflow = line.origin.y + line.size.height
- ( textView.contentOffset.y + textView.bounds.size.height
- textView.contentInset.bottom - textView.contentInset.top );
if ( overflow > 0 ) {
// We are at the bottom of the visible text and introduced a line feed, scroll down (iOS 7 does not do it)
// Scroll caret to visible area
CGPoint offset = textView.contentOffset;
offset.y += overflow + 7; // leave 7 pixels margin
// Cannot animate with setContentOffset:animated: or caret will not appear
[UIView animateWithDuration:.2 animations:^{
[textView setContentOffset:offset];
}];
}
}
The solution I found here was to add a one line fix after you create a UITextView:
self.textview.layoutManager.allowsNonContiguousLayout = NO;
This one line fixed three issues I had creating a UITextView-based code editor with syntax highlighting on iOS7:
- Scrolling to keep text in view when editing (the issue of this post)
- UITextView occasionally jumping around after dismissing the keyboard
- UITextView random scrolling jumps when trying to scroll the view
Note, I did resize the whole UITextView when the keyboard is shown/hidden.
Try implementing the -textViewDidChangeSelection:
delegate method from the UITextViewDelegate like this:
-(void)textViewDidChangeSelection:(UITextView *)textView {
[textView scrollRangeToVisible:textView.selectedRange];
}
Heres a modified version of the selected answer by davidisdk.
- (void)textViewDidChange:(UITextView *)textView {
NSRange selection = textView.selectedRange;
if (selection.location + selection.length == [textView.text length]) {
CGRect caretRect = [textView caretRectForPosition:textView.selectedTextRange.start];
CGFloat overflow = caretRect.origin.y + caretRect.size.height - (textView.contentOffset.y + textView.bounds.size.height - textView.contentInset.bottom - textView.contentInset.top);
if (overflow > 0.0f) {
CGPoint offset = textView.contentOffset;
offset.y += overflow + 7.0f;
[UIView animateWithDuration:0.2f animations:^{
[textView setContentOffset:offset];
}];
}
} else {
[textView scrollRangeToVisible:selection];
}
}
I was getting a bug that when the textView's content size is larger then the bounds and the cursor is offscreen (such as using a keyboard and pressing the arrow key) the textView wouldn't animate to the text being inserted.