How to make a UITextView scroll while typing/editing How to make a UITextView scroll while typing/editing ios ios

How to make a UITextView scroll while typing/editing

Problems with other answers:

  • when only scanning for "\n", if you type a line of text that exceeds the width of the text view, then scrolling will not occur.
  • when always setting contentOffset in textViewDidChange:, if you edit the middle of the text you do not want to scroll to the bottom.

The solution is to add this to the text view delegate:

- (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 - );    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];        }];    }}

I tried to put in your textViewDidChange: a snippet like:

if([textView.text hasSuffix:@"\n"])    [self.textView setContentOffset:CGPointMake(0,INT_MAX) animated:YES];

It's not really clean, I'm working toward finding some better stuff, but for now it works :D

UPDATE:Since this is a bug that only happens on iOS 7 (Beta 5, for now), you can do a workaround with this code:

if([textView.text hasSuffix:@"\n"]) {     double delayInSeconds = 0.2;     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));     dispatch_after(popTime, dispatch_get_main_queue(), ^(void){         CGPoint bottomOffset = CGPointMake(0, self.textView.contentSize.height - self.textView.bounds.size.height);         [self.textView setContentOffset:bottomOffset animated:YES];     }); }

Then, on iOS 6 you can choose either to set the delay to 0.0 or to use just the content of the block.

I used the following code in the textViewDidChange: method and it seemed to work well.

- (void)textViewDidChange:(UITextView *)textView {    CGPoint bottomOffset = CGPointMake(0, self.theTextView.contentSize.height - self.theTextView.bounds.size.height);    [self.theTextView setContentOffset:bottomOffset animated:YES];}

This seems to scroll the UITextView slightly further so that your cursor isn't cut off.