UITextView content offset changes after frame setting

I am creating a view very similar to a messaging app - I have a subview at the bottom of the page with UITextView

in it, and as the user enters and reaches the end of the line, the text view as since the view containing it needs to expand upward.

The way I work is that in the method textViewDidChange:

I call my layout function and this does

CGFloat textViewWidth = 200;
CGFloat textViewHeight = [self.textView sizeThatFits:CGSizeMake(textViewWidth, 2000)].height;
[self resizeParentWithTextViewSize:CGSizeMake(textViewWidth, textViewHeight)];

// And then the resize parent method eventually calls
textView.frame = CGRectMake(10, 10, textViewWidth, textViewHeight);

      

The problem is that when I type at the end of the line and the view expands, I get arbitrary contentOffset.y

something like 10.5 in the text view, so the text moves up to the top of the view. The weird thing is that it alternates on every other line, so the expansion leaves the content offset y shifted up the first time, then it approaches zero on the next line, then falls back to 10.5 on the next line, etc. (Not sure if this is useful or just a weird artifact of my values). I can set it back to zero, but it looks terrible because there is a momentary flash where the text has an offset value and then it is offset back to the middle.

I've read that it's usually better to use content inserts to scroll rather than resize the frame, but I don't understand how to do this because I also need to resize the frame.

How do I resize UITextView

without this? I think I can do without setting up the scrolling text, and that fixes the problem, but I would like to understand what is going on.

+3


source to share


4 answers


The customization textView.scrollable = NO

allows me to resize the text view without any weird offsets, which is the only way I could figure out. And I'm guessing this isn't too much of a limitation for common scenarios, if you want the text view to be scrollable, you probably don't need to resize it on the fly as the user can navigate as the content changes.



+1


source


The problem is that the UITextView's scroll animation and the border setting action were done at the same time. The UITextView internally scrolls the texts you are currently typing, visible when typed another character at the end of a line, or typed a new character in a line. But the scroll animation is unnecessary because you are expanding the text. Unfortunately, we cannot control the internal scroll action of the textview to make the text scroll to the top of the expanded text. And this strange scroll also makes an unnecessary bottom padding.

You can avoid this weird action very simply by overriding UITextView setContentOffset: animated: like this.

Objective-C

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated {
    [super setContentOffset:contentOffset animated:NO];
}

      



Swift

override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
    super.setContentOffset(contentOffset, animated: false)
}

      

This code avoids the automatic sorting of the UITextView with unnecessary scroll animations, and you can freely expand the size of the text view.

+2


source


I faced the same problem: changing the frame UITextView

to fit its content had the side effect of the wrong scroll position. Scrolling UITextView

even if contentSize

matches bounds

.

I ended up setting scrollEnabled

to true

and adjusting the content offset if UITextView

it doesn't actually scroll

override var contentOffset: CGPoint {
    didSet {
        if iOS8 {
            // here the contentOffset may become non zero whereas it shouldn't be
            if !isContentScrollable && contentOffset.y > 0 {
                contentOffset.y = 0
            }
        }
    }
}    

var isContentScrollable: Bool {
    let result = ceil(contentSize.height) > ceil(height)
    return result
}

      

0


source


In fact, I ran into the same problem and found that it actually only happens when the UITextView has any Autolayout constraints. If you try to use the UITextView without applying any restrictions, it will not happen and will work fine. but when applying auto-layout constraints, it automatically scrolls down. To handle this, I simply add the method

-(void)viewDidLayoutSubviews{
  [super viewDidLayoutSubviews];
  self.textView.contentOffset = CGPointZero;
}

      

0


source







All Articles