Resize a UITextField while typing (by using Autolayout)

Matthias Bauch picture Matthias Bauch · Aug 14, 2013 · Viewed 29.5k times · Source

I have a UITableViewCell which has two UITextFields (without borders). The following constraints are used to set up the horizontal layout.

@"|-10-[leftTextField(>=80)]-(>=10)-[rightTextField(>=40)]-10-|"

Nothing fancy, and works as expected.

enter image description here

As you can see the upper textField has the correct size. The lower textField started with an empty text, and because of the empty text it is 80 points wide. When I type text into the editing textField the text scrolls to the left, it does not change its width.

I don't like that, the width of the textField should adjust while the user types into that textField.

In my opinion that should work out of the box. By implementing a IBAction for the UIControlEventEditingChanged event I can confirm that typing actually changes the intrinsicContentSize of the UITextField.

But well, the width does not change until the textField is no longer the first responder. If I put the cursor into another textField the width of the edited textField is set. That's a bit late for what I want.

These commented out lines is what I tried without any success:

- (IBAction)textFieldDidChange:(UITextField *)textField {
    [UIView animateWithDuration:0.1 animations:^{
//        [self.contentView removeConstraints:horizontalConstraints];
//        [self.contentView addConstraints:horizontalConstraints];
//        [self.contentView layoutIfNeeded];

//        [self.contentView setNeedsLayout];

//        [self.contentView setNeedsUpdateConstraints];
    }];
    NSLog(@"%@", NSStringFromCGSize(textField.intrinsicContentSize));
}

Does anybody know what I am missing? What could I try to make this work?

Answer

TomSwift picture TomSwift · Aug 16, 2013

This is what works for me:

- (IBAction) textFieldDidChange: (UITextField*) textField
{
    [UIView animateWithDuration:0.1 animations:^{
        [textField invalidateIntrinsicContentSize];
    }];
}

What's interesting is that it seems as if it SHOULD work out of the box, given this text from the docs:

In addition, if a property of a view changes and that change affects the intrinsic content size, the view must call invalidateIntrinsicContentSize so that the layout system notices the change and can re-layout. In the implementation of your view class, you must ensure that if the value of any property upon which the intrinsic size depends changes, you invoke invalidateIntrinsicContentSize. For example, a text field calls invalidateIntrinsicContentSize if the string value changes.

My best guess is that the textfield only calls invalidateIntrinsicContentSize once editing has finished, not during.

Edit: A bunch of "This is not working for me". I think the confusion here is perhaps the triggering event that is tied to the textFieldDidChange: handler. The event needs to be UIControlEventEditingChanged. If you're using IB, double check that you're handling the right event.

The UITextField also cannot be constrained in size. You can lock it into position with constraints, but any width constraint, or set of left+right positioning constraints will prevent it from resizing to its intrinsic content size.