iOS: UITextView set height equal to content height

2020-03-31 12:28发布

问题:

I have a UITextView with disabled scrolling and I need to set the height of the UITextView to match the height of the text content. I have tried various methods found the internet with no results. This is my code for the layout of the UITextView:

-(void) viewDidLayoutSubviews {
    // UITextView is named jobDescrip
    jobDescrip.scrollEnabled = NO;
    [jobDescrip sizeToFit];
    [jobDescrip layoutIfNeeded];
}

I have also tried this code in the viewDidAppear: method. Can someone please post code for an iOS 7.0 and later solution to this problem using auto layout?

回答1:

Have you tried this? I added a button, with the flowing code in its action method I can see the height is changed to the text height.

CGSize size = [self.textView systemLayoutSizeFittingSize:self.textView.contentSize];
CGRect frame = self.textView.frame;
frame.size.height = size.height;
self.textView.frame = frame;

Edit

I added a bottom space to superview constraint and set it as IBOutlet property,then in viewDidAppear I changed the constraint constant.

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.textView.contentInset = UIEdgeInsetsZero;
    CGSize size = [self.textView systemLayoutSizeFittingSize:self.textView.contentSize];
    self.heightConstraint.constant -= size.height - self.textView.frame.size.height;
    self.textView.scrollEnabled = NO;
    [self.textView setNeedsUpdateConstraints];
}


回答2:

These are the couple of libraries handling resizing UITextView while user enters text.

  1. CSGrowingTextView: This is a UITextView subclass which resizes self according to its content. This works well for both autolayout and non-autolayout. This provides some more control over resize animation via following properties and delegate methods.

    @property (nonatomic, readwrite) CSGrowDirection growDirection;
    @property (nonatomic, readwrite) NSTimeInterval growAnimationDuration;
    @property (nonatomic, readwrite) UIViewAnimationOptions;
    
    - (void)growingTextView:(CSGrowingTextView *)growingTextView willChangeHeight:(CGFloat)height;
    - (void)growingTextView:(CSGrowingTextView *)growingTextView didChangeHeight:(CGFloat)height;
    
  2. ResizableTextView: This is again a UITextView subclass which encapsulate all size-changing related code.This is based on autolayout. This searches for height constraint added to textView and updates it with calculated content size. Here is the sample usage.

    [self.view layoutIfNeeded];
    // do your own text change here.
    self.infoTextView.text = [NSString stringWithFormat:@"%@, %@", self.infoTextView.text, self.infoTextView.text];
    [self.infoTextView setNeedsUpdateConstraints];
    [self.infoTextView updateConstraintsIfNeeded];
    [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
         [self.view layoutIfNeeded];
    } completion:nil]
    
  3. MBAutoGrowingTextView: This is one of the elegant solutions based in auto-layout. This UITextView subclass automatically grows and shrinks based on content and can be constrained by maximal and minimal height - all without a single line of code.

    1. Give appropriate horizontal constraint
    2. If you want textView to grow upwards, pin to bottom. Otherwise pin it to the top.
    3. To limit maximal height, add the height constant with relation "Less than or equal" to some maximum value.
    4. To limit minimal height, add the height constant with relation "Greater than or equal" to some minimum value.
    
  4. GrowingTextViewHandler:This an NSObject subclass which encapsulated the code for resizing UITextView. This approach is based on autolayout. Handling resize out of UITextView subclass gives much more flexibility. First, GrowingTextViewHandler does not have to worry about handling UITextViewDelegates. Second it will work for any UITextView subclass.

    /*You need to pin UITextView appropriately.
      1. Give appropriate horizontal constraint
      2. Give height constraint
      3. To grow upwards, give bottom constraint
         To grow downwards, give top constraint
         To grow both directions, pin it vertically center
    */
    
    @interface ViewController ()<UITextViewDelegate>
      @property (weak, nonatomic) IBOutlet UITextView *textView;
      @property (weak, nonatomic) IBOutlet NSLayoutConstraint *heightConstraint;
      @property (strong, nonatomic) GrowingTextViewHandler *handler;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
       [super viewDidLoad];
       self.handler = [[GrowingTextViewHandler alloc]initWithTextView:self.textView withHeightConstraint:self.heightConstraint];
       [self.handler updateMinimumNumberOfLines:3 andMaximumNumberOfLine:8];
      }
    
      - (void)textViewDidChange:(UITextView *)textView {
        [self.handler resizeTextViewWithAnimation:YES];
      }
     @end
    


回答3:

Try adding this line to your method:

[jobDescrip.textContainer setSize:jobDescrip.frame.size];

and see if it works, if not, try using a UILabel instead of a UITextView, setting its numberOfLines to 0, and adding this method:

- (float)getHeightFortheDynamicLabel:(NSString *)stringForTheLabel
{
    CGSize maxSize = CGSizeMake(215, 2000.0);
    CGSize newSize = [stringForTheLabel sizeWithFont:[UIFont systemFontOfSize:14.0]
                                   constrainedToSize:maxSize]; //Remember to ensure the font size is both the same in here, and in the label properties.
    return newSize.height;
}