简体   繁体   中英

How to automatically change height of UILabel object and position of other elements below, based on the content of UILabel, with autolayout enabled

I've found some answers related to this topic, but nothing works for me. I've tried setPreferredMaxLayoutWidth: , setting number of lines to 0, setting height constraint to XYZ, or equal or greater than XYZ... and all that in many different combinations. What could be possibly wrong? Any ideas?

在此处输入图片说明

Selected label is the one that needs to change the height based on content. Label below it, and possible other elements below should move down if the label has content that doesn't fit in 1 line. There are no constraint problems reported by IB.

Here's how I've just successfully done it:

  1. I set numberOfLines on the label to 0, so it will grow and shrink as necessary.
  2. I gave the label >= 0 left and right leading/trailing space constraints to the container margins, so it can grow to a maximum width.
  3. I did not put any height constraint on the label. The height will therefore be determined by the content.
  4. I made sure that no vertical constraints on anything below the label were limiting its downward growth.

In particular, bear in mind that if you set a constraint from anything to the bottom of the screen, you'll need to make sure that its priority (or the priority of another vertical constraint in the chain from the label to the bottom) is set to a lower priority than the vertical Content Compression Resistance Priority of the label. This will make sure that the growth of the label's content can overcome the other vertical constraints.

结果图片

If you are using Auto Layout in code, setting the frame does not work. You have to create the constraint set required for the layout you want. For this case you would need to add height constraints for your UILabel.

Full tutorial on how to do is here : http://www.thinkandbuild.it/learn-to-love-auto-layout-programmatically/

if you want to try to take care of it in code then you can approach it like this. i've laid out something akin to what you have then after 5 seconds it will swap in a new vertical constraint to make one of the labels taller. hope it steers you in the right direction ... or at least a direction!

NSArray * vertConstraint;

UIImageView * imageView = [[UIImageView alloc] init];
UILabel * labelOne = [[UILabel alloc] init];
UILabel * labelTwo = [[UILabel alloc] init];
UILabel * labelThree = [[UILabel alloc] init];

imageView.backgroundColor = [UIColor grayColor];
labelOne.backgroundColor = [UIColor redColor];
labelTwo.backgroundColor = [UIColor blueColor];
labelThree.backgroundColor = [UIColor orangeColor];

[imageView setTranslatesAutoresizingMaskIntoConstraints: NO];
[labelOne setTranslatesAutoresizingMaskIntoConstraints: NO];
[labelTwo setTranslatesAutoresizingMaskIntoConstraints: NO];
[labelThree setTranslatesAutoresizingMaskIntoConstraints: NO];

[self.view addSubview:imageView];
[self.view addSubview:labelOne];
[self.view addSubview:labelTwo];
[self.view addSubview:labelThree];

id topGuide = self.topLayoutGuide;
id bottomGuide = self.bottomLayoutGuide;

NSDictionary * viewsDictionary = NSDictionaryOfVariableBindings(imageView, labelOne,labelTwo,labelThree,topGuide, bottomGuide);

// initial vertical constraints.  will be swapped out after 5 seconds (See below
vertConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topGuide]-100-[imageView(==200)]-20-[labelOne(==20)]-20-[labelTwo(==20)]-20-[labelThree(==20)]-(>=5)-[bottomGuide]|" options:0 metrics: 0 views:viewsDictionary];

[self.view addConstraints:vertConstraint];

// horizontal constraints for all the elements
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=0)-[imageView(==200)]-(>=0)-|" options:0 metrics: 0 views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=0)-[labelOne(==200)]-(>=0)-|" options:0 metrics: 0 views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=0)-[labelTwo(==200)]-(>=0)-|" options:0 metrics: 0 views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=0)-[labelThree(==200)]-(>=0)-|" options:0 metrics: 0 views:viewsDictionary]];

//additional constraints to center them    
[self.view addConstraint:
 [NSLayoutConstraint constraintWithItem:imageView
                              attribute:NSLayoutAttributeCenterX
                              relatedBy:NSLayoutRelationEqual
                                 toItem:self.view
                              attribute:NSLayoutAttributeCenterX
                             multiplier:1
                               constant:0]];

[self.view addConstraint:
 [NSLayoutConstraint constraintWithItem:labelOne
                              attribute:NSLayoutAttributeCenterX
                              relatedBy:NSLayoutRelationEqual
                                 toItem:self.view
                              attribute:NSLayoutAttributeCenterX
                             multiplier:1
                               constant:0]];


[self.view addConstraint:
 [NSLayoutConstraint constraintWithItem:labelTwo
                              attribute:NSLayoutAttributeCenterX
                              relatedBy:NSLayoutRelationEqual
                                 toItem:self.view
                              attribute:NSLayoutAttributeCenterX
                             multiplier:1
                               constant:0]];

[self.view addConstraint:
 [NSLayoutConstraint constraintWithItem:labelThree
                              attribute:NSLayoutAttributeCenterX
                              relatedBy:NSLayoutRelationEqual
                                 toItem:self.view
                              attribute:NSLayoutAttributeCenterX
                             multiplier:1
                               constant:0]];

//delay 5 seconds then swap out vertical constraints
// in this case change the (==20) to (==40) for height of element
// you can edit that string more dynamically to fit your needs
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{

    NSArray * newVertConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topGuide]-100-[imageView(==200)]-20-[labelOne(==20)]-20-[labelTwo(==40)]-20-[labelThree(==20)]-(>=5)-[bottomGuide]|" options:0 metrics: 0 views:viewsDictionary];

    [self.view removeConstraints:vertConstraint];
    [self.view addConstraints:newVertConstraint];
    [self.view setNeedsUpdateConstraints];
    [UIView animateWithDuration:1.5 animations:^{
        [self.view layoutIfNeeded];
    }];


});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM