9

I have an UITextView which in iOS 7 behaves fine. In iOS 8 it behaves weird.

When I enter text which becomes two lines, I update the size of the inputView, which contains the textview. I also update the size of the textview but somehow it seems to scroll away the first line; yet this is not reflected in its size.

Video for behavior in iOS 7 (correct): https://www.dropbox.com/s/rr4pea6wudobmk8/iOS7.mov

Video for behavior in iOS 8: https://www.dropbox.com/s/iyqrsp41uz5mn85/iOS8.mov

I have set [self setAutomaticallyAdjustsScrollViewInsets:NO];, but no change. This didn't help me: What is Causing this Unwanted Content Inset with UITextView in iOS 8 (not there in iOS 7)?

There are the results from my NSLog in iOS8:

2014-12-22 02:02:48.104 Date For Date[68577:10129965] DID BEGIN: textContainerInset Top: 8.000000 - contentInset Bottom: 0.000000 - scrollIndicatorInset: 10.000000
2014-12-22 02:02:50.579 Date For Date[68577:10129965] DID CHANGE: textContainerInset Top: 8.000000 - contentInset Bottom: 0.000000 - scrollIndicatorInset: 10.000000
2014-12-22 02:02:50.768 Date For Date[68577:10129965] DID CHANGE: textContainerInset Top: 8.000000 - contentInset Bottom: 0.000000 - scrollIndicatorInset: 10.000000
2014-12-22 02:02:50.960 Date For Date[68577:10129965] DID CHANGE: textContainerInset Top: 8.000000 - contentInset Bottom: 0.000000 - scrollIndicatorInset: 10.000000
2014-12-22 02:02:51.168 Date For Date[68577:10129965] DID CHANGE: textContainerInset Top: 8.000000 - contentInset Bottom: 0.000000 - scrollIndicatorInset: 10.000000
2014-12-22 02:02:52.145 Date For Date[68577:10129965] DID CHANGE: textContainerInset Top: 8.000000 - contentInset Bottom: 0.000000 - scrollIndicatorInset: 10.000000
2014-12-22 02:02:52.408 Date For Date[68577:10129965] DID CHANGE: textContainerInset Top: 8.000000 - contentInset Bottom: 0.000000 - scrollIndicatorInset: 10.000000

This is my code:

- (void)textViewDidBeginEditing:(UITextView *)textView
{
    [textView becomeFirstResponder];

    if(!self.previousTextViewContentHeight)
        self.previousTextViewContentHeight = textView.contentSize.height;

    [self _scrollToBottom:YES];

    NSLog(@"DID BEGIN: textContainerInset Top: %f - contentInset Bottom: %f - scrollIndicatorInset: %f", textView.textContainerInset.top, textView.contentInset.top, textView.scrollIndicatorInsets.top);
}

- (void)textViewDidEndEditing:(UITextView *)textView
{
    [textView resignFirstResponder];
}

- (void)textViewDidChange:(UITextView *)textView
{
    // Textfield
    NSLog(@"DID CHANGE: textContainerInset Top: %f - contentInset Bottom: %f - scrollIndicatorInset: %f", textView.textContainerInset.top, textView.contentInset.top, textView.scrollIndicatorInsets.top);

    CGFloat maxHeight = [JSMessageInputView maxHeight];
    CGFloat textViewContentHeight = MIN(textView.contentSize.height, maxHeight);

    CGFloat changeInHeight = textViewContentHeight - self.previousTextViewContentHeight;

    self.previousTextViewContentHeight = MIN(textViewContentHeight, maxHeight);

    if(changeInHeight != 0.0f) {
        textView.frame = CGRectMake(6, 3, textView.frame.size.width, textView.frame.size.height + changeInHeight);

        textView.contentInset = UIEdgeInsetsMake(0.0f,
                                                 0.0f,
                                                 0.0f,
                                                 0.0f);

        [textView setContentSize:CGSizeMake(textView.contentSize.width, textView.contentSize.height + changeInHeight)];

        // Change table
        UIEdgeInsets insets = UIEdgeInsetsMake(0, 0.0f, self.bubbleTable.contentInset.bottom + changeInHeight, 0.0f);
        self.bubbleTable.contentInset = insets;
        self.bubbleTable.scrollIndicatorInsets = insets;

        [self _scrollToBottom:YES];

        // Change input view
        CGRect inputViewFrame = self.inputView.frame;
        self.inputView.frame = CGRectMake(0.0f,
                                          inputViewFrame.origin.y - changeInHeight,
                                          inputViewFrame.size.width,
                                          inputViewFrame.size.height + changeInHeight);
    }

    self.inputView.sendButton.enabled = ([textView.text trimWhitespace].length > 0);
}

What am I doing wrong?

Community
  • 1
  • 1
Paul Peelen
  • 10,073
  • 15
  • 85
  • 168
  • Please attach a sample project. – Léo Natan Dec 26 '14 at 18:32
  • Don't have one for you just yet, as soon as I find the time... I'll make one. Sorry :( – Paul Peelen Dec 29 '14 at 16:39
  • You have a bounty open. I would like to help. – Léo Natan Dec 29 '14 at 16:41
  • I've seen something similar to this with an interesting manifestation. Can you NSLog the textview.frame.size.width on the same phone simulator and compare iOS 7 vs 8. I have a hunch that the iOS 8 width will be smaller than the iOS 7 width, so all of the text calculations will therefore be off. Check it out and let me know. – Mike Dec 29 '14 at 17:49
  • I don't remember how I fix it before :(. But look at your code, I think the problem may be the textView `contentSize` is added twice caused `[textView setContentSize:CGSizeMake(textView.contentSize.width, textView.contentSize.height + changeInHeight)]; `. Try to use `textView setNeedLayout` instead. Hope that help – sahara108 Dec 30 '14 at 10:07
  • Please provide details about your textfield constraints and frame. – Mrunal Dec 30 '14 at 11:34
  • 1
    This might helps you : https://github.com/slackhq/SlackTextViewController – Yuyutsu Dec 30 '14 at 18:33

2 Answers2

3

Why you don't use UITextView sizeThatFits function? It will automatically calculate correct height with all padding:

CGFloat textViewHeight = [textView sizeThatFits:CGSizeMake(textView.frame.size.width, MAXFLOAT)].height;
Vitalii Gozhenko
  • 9,220
  • 2
  • 48
  • 66
1

Try textView.textContainer.lineFragmentPadding = 0; in addition to textView.textContainerInset = UIEdgeInsetsZero;. This makes my text hug the bounds of the UITextView.

ad121
  • 2,268
  • 1
  • 18
  • 24