5

I am doing a test project, and came across a problem with UITextView.

I am dynamically getting the content size of the text in the text view, and then increasing its height when needed. When the height reaches the threshold I have set, I will set scrollEnabled = YES to enable scrolling. Weird thing seems to happen as shown in the following screen shots:

Before going to new line and enabling scrolling:

enter image description here

After entering the next character, which will enable the scrolling:

enter image description here

After that, entering another character again, the text view will become normal again with scroll enabled (in fact the height remains as in the previous screen shot, I change the height according to content size, so it become the same height before enable scroll):

enter image description here

Anyone has came across this problem and able to solve it? If this is an iOS7 bug, any other suggestion for creating a message input text box? I wonder if previous iOS versions have this problem though.

Edited:

It seems like this problem occurs when the textview's scrollEnabled is YES and change the textview.frame.size.height, then the height will reset to the initial height (as in the height set in Interface Builder). Wonder if this will help for this problem.

The following shows the code used for editing the height of the text view (it is a method for the selector which will be called upon received UITextViewTextDidChangeNotification):

NSInteger maxInputFieldWidth = self.inputTextField.frame.size.width;

CGSize maxSize = CGSizeMake(maxInputFieldWidth, 9999);
CGSize neededSize = [self.inputTextField sizeThatFits:maxSize];

NSInteger neededHeight = neededSize.height;

if (self.inputTextField.hasText)
{
    [self.inputTextField scrollRangeToVisible:NSMakeRange([self.inputTextField.text length], 0)];

    if (neededHeight <= TEXTVIEW_MAX_HEIGHT_IN_USE && neededHeight != previousHeight)
    {
        previousHeight = neededHeight;

        CGRect inputTextFieldFrame = self.inputTextField.frame;
        inputTextFieldFrame.size.height = neededHeight;
        inputTextFieldFrame.origin.y = TEXTVIEW_ORIGIN_Y;
        self.inputTextField.frame = inputTextFieldFrame;
    }
    else if (neededSize.height > TEXTVIEW_MAX_HEIGHT_IN_USE)
    {
        if (!self.inputTextField.scrollEnabled)
        {
            self.inputTextField.scrollEnabled = YES;

            CGRect inputTextFieldFrame = self.inputTextField.frame;
            inputTextFieldFrame.size.height = TEXTVIEW_MAX_HEIGHT_IN_USE;
            inputTextFieldFrame.origin.y = TEXTVIEW_ORIGIN_Y;
            self.inputTextField.frame = inputTextFieldFrame;
        }
        else if (neededHeight != previousHeight)
        {
            previousHeight = neededHeight;

            CGRect inputTextFieldFrame = self.inputTextField.frame;
            inputTextFieldFrame.size.height = TEXTVIEW_MAX_HEIGHT_IN_USE;
            inputTextFieldFrame.origin.y = TEXTVIEW_ORIGIN_Y;
            self.inputTextField.frame = inputTextFieldFrame;
        }
    }
}
L.C. Tan
  • 139
  • 1
  • 13
  • Perhaps you can upload the code that you are using to resize the textview? – Tcharni Mar 14 '14 at 02:05
  • just edited the question, added the code block to resize textview, self.inputTextField is the UITextView – L.C. Tan Mar 14 '14 at 02:25
  • Doesn't seem to be anything wrong with your code. Try placing previousHeight = neededHeight; inside the if(!self.inputTextField.scrollEnabled) loop, and see if it works. – Tcharni Mar 14 '14 at 02:42
  • err... the UITextView was added in the InterfaceBuilder, does this made any cause to my problem? – L.C. Tan Mar 14 '14 at 03:18
  • Should not be a problem unless you forgot to set up the outlets and the ibaction references. – Tcharni Mar 14 '14 at 03:33
  • However, I would use the MIN (A, B) function to set the content height of the textView – Tcharni Mar 14 '14 at 03:34

3 Answers3

3

Over a year later and scrollEnabled is still causing problems. I had a similar issue where setting scrollEnabled = true (I'm using Swift) would not cause any changes.

I solved the problem by setting autolayout constraints on all sides of the textView. Then, like you detailed here, I just set textView.frame again. My guess is that this causes some internal update, which actually turns scrolling on. I'm also guessing that autolayout then forces the textView to stay at the right height, as opposed to the collapse that you're experiencing.

Cameron Sun
  • 423
  • 1
  • 4
  • 9
  • Absolutely correct, this should be the accepted answer. Just to add on this, you **do not** need to change the frame size, you can just put this code: `textView.frame = textView.frame` – Ivan Jul 21 '15 at 11:29
2

The brilliant Pete Steinberger has had a lot of problems with the UITextView and implemented a lot of fixes as a result.

His article can be found here with links to his code.

For a direct link to the code, it can be found here, but I recommend reading the post.

Infinity James
  • 4,667
  • 5
  • 23
  • 36
  • it doesn't work...i thk this issue is different than any others that I could found using Google. – L.C. Tan Mar 17 '14 at 06:15
  • http://stackoverflow.com/questions/20632830/uitextview-with-scroll-dynamically-set-resizes-to-default My problem is similar to this one, though no answer yet – L.C. Tan Mar 17 '14 at 07:22
2

I ran into a similar issue (I'm using auto-layout) and was able to solve it with the following set up:

  1. Adding top, leading, bottom, trailing margin constraints to my text view
  2. Adding a greater-than-or-equal-to minimum height constraint with priority 999 (in my case this was set to 50)
  3. Adding a less-than-or-equal-to maximum height constraint with priority 1000 (in my case this was set to 125)
  4. Adding an equal-to height constraint with priority 1000 (set to 125) and making sure it's not installed (uncheck the 'installed' option in Interface Builder or set 'active' to NO/false on the constraint in code)

I then use the following code to determine the height of the text view and enable/disable scroll and constraints:

- (void)textViewDidChange:(UITextView *)textView {
    ...

    CGSize size = textView.bounds.size;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(size.width, CGFLOAT_MAX)];

    if (newSize.height >= self.textViewMaxHeightConstraint.constant
        && !textView.scrollEnabled) {
        textView.scrollEnabled = YES;
        self.textViewHeightConstraint.active = YES;
    } else if (newSize.height < self.textViewMaxHeightConstraint.constant
               && textView.scrollEnabled) {
        textView.scrollEnabled = NO;
        self.textViewHeightConstraint.active = NO;
    }

    ...
}

Using sizeThatFits: to determine the desired size of the text view, I either set scroll enabled or disabled. If it's enabled, I set the height constraint to active to force the text view to stay at the desired height.

ppilone
  • 1,082
  • 1
  • 10
  • 16