mad_dog
mad_dog

Reputation: 158

ios Autolayout - move 2nd view when 1st view resized

My main view consists of a scrollview, with several textfields as part of a form. I then have a textView (actually a HPGrowingTextView) which resizes the textview vertically as text/lines are added. Beneath this textview is a mkmapview. Autolayout works fine for the initial layout, however when the textview resizes itself, the mapview doesn't move (you can see in the screenshot how the textview's border has disappeared behind the mapview which is still in its original spot.

The mapview's TopSpace constraint is set to 8 from the GrowingTextView.Bottom so I would have thought it should automatically stay 8 pixels (or whatever) from the textview at all times.

(I am using Storyboards... the GrowingTextView is a UIView dragged in on the storyboard and set/subclassed as HPGrowingTextView. Other than the mapview not moving... it works correctly (tested it without the mapview)

Upvotes: 2

Views: 192

Answers (2)

mad_dog
mad_dog

Reputation: 158

If you're not looking for additional functionality, it turns out to be reasonably easy to just use the standard UITextView.

  1. Insert a UITextView, and add your usual auto-layout constraints. In my example I have a few UITextFields, then my UITextView, followed by a MKMapView. Each is constrained to sit 8 below the previous item. (See screenshot in original post). Create an IBOutlet for the UITextView as usual. Don't forget to conform to UITextViewDelegate.
  2. Add an outlet in your class/view's .h file, so that you can set/change the height constraint when needed. In Storyboard, alt-click on the UITextView's height constraint, and connect it to the IBOutlet in the .h file.

@property (nonatomic, strong) IBOutlet NSLayoutConstraint *heightConstraint;

enter image description here

  1. Add the following methods to your .m file.

    - (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString*)text {
        // if the text has updated, resize the view accordingly
        [self resizeTextViewToFitContent:textView];
        return YES;
    }
    
    - (void)resizeTextViewToFitContent:(UITextView *)textView {
        CGRect frame = textView.frame;
        frame.size.height=[self heightOfTextView:textView];
        textView.frame=frame;
    }
    
    -(CGFloat)heightOfTextView:(UITextView *)textView {
        // because i've set a minimum height for the textview 
        // (which is the same as the height i set in the Storyboard/constraints, 
        // set the new size to whatever is larger 
        // - the required size or the minimum size.
        CGFloat val = MAX(_minTextViewHeight,self.addressTextView.intrinsicContentSize.height);
        return val;
    }
    
    -(IBAction)textViewDidChange:(UITextView *)textView {
        // update the constraint based on the size we expect the view to be.
        // because this is an IBOutlet, it then updates on the screen.
        self.heightConstraint.constant = [self heightOfTextView:self.addressTextView];
     }
    

This seems to work fairly flawlessly for me at the moment in terms of adjusting the textview size, whilst maintaining the constraints to the mkmapview. The mapview now moves down or up as the textview grows/shrinks :-)

Upvotes: 2

Ken Thomases
Ken Thomases

Reputation: 90681

It appears that HPGrowingTextView is not auto-layout-compatible. It doesn't implement -intrinsicContentSize. Nor does it add any constraints. Instead, it just sets its own frame.

In auto layout, setting frames is not effective. You have to adjust constraints. (A view changing its intrinsic content size has the effect of adjusting some constraints that the system implicitly creates.) Any changes to frames will just be undone by the next layout pass.

Frankly, I'm somewhat surprised that the initial layout is sensible. Do you have height constraints or something else to compensate for the fact that the HPGrowingTextView doesn't have an intrinsic size?

Anyway, you will need to switch to an auto-layout-aware view or fix HPGrowingTextView.

Upvotes: 2

Related Questions