Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSTextFields with auto-layout; grow into space as typing

I want to layout my view with these requirements: a) there are 2 text fields, both with a minimum width of 90 b) I want the text fields to maintain a gap of 10 between them at all times c) I want the text field that is being typed-in to grow bigger as needed, and start taking up the empty space on the right. If the first field is being types, it should grow bigger and push the last field into the space (only increasing first field's width, of course) d) I want the text fields to stop growing after they get close to the right edge of the view (standard 20 px) e) the height constraints are simple: just 22px, aligned at the top with the top of the picture

Here is the layout that I want:

enter image description here

Here are the constraints: enter image description here

I've tried everything, and I can't get this to work. I can get one text field to increase correctly as you type in (using the answer from this link: getting a NSTextField to grow with the text in auto layout?) but can't get it to work with the 2nd text field next to it, pushing it to occupy the empty space. I've played around with the content hugging / compression resistance priorities, with giving the text fields >=90 widths (with a pin the right) ... nothing seems to setup correctly in IB (using Xcode 5.1). It complains about constraint ambiguity if I add the width constraints, or complains about missing constraints without a width.

Any ideas how to get this to work?

EDIT:

This is how I imagine the ideal layout to look: with a constraint to be less than 400 pinning on the right. But it still complains about "Inequality constraint ambiguity" there.

enter image description here

like image 470
Z S Avatar asked Nov 10 '22 10:11

Z S


1 Answers

It's been almost a year since this was asked, but I think it's a really good question that deserves an answer so I set out to solve your problem and managed to fix it in a pretty simple way.

You can find a sample project in Github by clicking here.

Bare in mind, I did it using UIKit, so I hope you have the same APIs in the Desktop Framework.

First I setup the constraints like this:

firstTextField: {
    Leading = 20pt (to superView), 
    Width >= 90pt,
    Trailing = 10pt (to secondTextField),
    Vertical Align Y (to superView)
}

secontTextField: {
    Leading = 10pt (to firstTextField), 
    Width >= 90pt,
    Trailing = 20pt (to superView),
    Vertical Align Y (to superView)
}

That's it for interface. Now, in code you need an outlet to the firstTextField and also a callback method for when the text has changed. Then, in this method you must invalidate the firstTextField's instrinsicContentSize:

@interface ViewController () <UITextFieldDelegate>

@property (weak, nonatomic) IBOutlet UITextField *firstTextField;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self.firstTextField addTarget:self
                            action:@selector(textFieldDidChange)
                  forControlEvents:UIControlEventEditingChanged];
}

- (void)textFieldDidChange
{
    [self.firstTextField invalidateIntrinsicContentSize];
}

@end
like image 62
Pedro Mancheno Avatar answered Dec 01 '22 00:12

Pedro Mancheno