Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Instead of resizing the frame, why not give your text view a <code>contentInset</code> (and a matching <code>scrollIndicatorInsets</code>)? Remember that text views are actually scrollviews. This is the correct way to handle keyboard (or other) interference.</p> <p>For more information on <code>contentInset</code>, see <a href="https://stackoverflow.com/questions/1983463/whats-the-uiscrollview-contentinset-property-for">this</a> question.</p> <hr> <p>This seems to not be enough. Still use insets, as this is more correct (especially on iOS7, where the keyboard is transparent), but you will also need extra handling for the caret:</p> <pre><code>- (void)viewDidLoad { [super viewDidLoad]; [self.textView setDelegate:self]; self.textView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_keyboardWillShowNotification:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_keyboardWillHideNotification:) name:UIKeyboardWillHideNotification object:nil]; } - (void)_keyboardWillShowNotification:(NSNotification*)notification { UIEdgeInsets insets = self.textView.contentInset; insets.bottom += [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; self.textView.contentInset = insets; insets = self.textView.scrollIndicatorInsets; insets.bottom += [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; self.textView.scrollIndicatorInsets = insets; } - (void)_keyboardWillHideNotification:(NSNotification*)notification { UIEdgeInsets insets = self.textView.contentInset; insets.bottom -= [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height; self.textView.contentInset = insets; insets = self.textView.scrollIndicatorInsets; insets.bottom -= [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height; self.textView.scrollIndicatorInsets = insets; } - (void)textViewDidBeginEditing:(UITextView *)textView { _oldRect = [self.textView caretRectForPosition:self.textView.selectedTextRange.end]; _caretVisibilityTimer = [NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:@selector(_scrollCaretToVisible) userInfo:nil repeats:YES]; } - (void)textViewDidEndEditing:(UITextView *)textView { [_caretVisibilityTimer invalidate]; _caretVisibilityTimer = nil; } - (void)_scrollCaretToVisible { //This is where the cursor is at. CGRect caretRect = [self.textView caretRectForPosition:self.textView.selectedTextRange.end]; if(CGRectEqualToRect(caretRect, _oldRect)) return; _oldRect = caretRect; //This is the visible rect of the textview. CGRect visibleRect = self.textView.bounds; visibleRect.size.height -= (self.textView.contentInset.top + self.textView.contentInset.bottom); visibleRect.origin.y = self.textView.contentOffset.y; //We will scroll only if the caret falls outside of the visible rect. if(!CGRectContainsRect(visibleRect, caretRect)) { CGPoint newOffset = self.textView.contentOffset; newOffset.y = MAX((caretRect.origin.y + caretRect.size.height) - visibleRect.size.height + 5, 0); [self.textView setContentOffset:newOffset animated:YES]; } } -(void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } </code></pre> <p>A lot of work, Apple should provide better way of handling the caret, but this works.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload