简体   繁体   中英

Subview vertical align middle in view with auto layout constraints programmatically

I need to locate a subview vertical align middle in a view without hardcode the top value 150 using constraint programmatically. I wish to achieve something like below:

在此处输入图片说明

Below is my code so far, Please advise.

import UIKit

class MainViewController: UIViewController {
 var viewInner:UIView = UIView()
    var viewOuter:UIView = UIView()


    override func viewDidLoad() {
        super.viewDidLoad()

        viewInner.backgroundColor = UIColor.redColor()
        viewOuter.backgroundColor = UIColor.purpleColor()
        viewOuter.frame = CGRectMake(100, 100, 400, 400)

        viewInner.setTranslatesAutoresizingMaskIntoConstraints(false)

        let viewsDictionary = ["viewInner":viewInner]

        viewOuter.addSubview(viewInner)
        self.view.addSubview(viewOuter)

        //Add Constraint

        var constOuterH = NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[viewInner(>=200)]-10-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
        var constOuterV = NSLayoutConstraint.constraintsWithVisualFormat("V:|-150-[viewInner(100)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)

        viewOuter.addConstraints(constOuterH)
        viewOuter.addConstraints(constOuterV)
    }
}

You need to use the non-visual formatting way of adding constraints:

[self.view addConstraint:[NSlayoutConstraint constraintWithItem:self.viewOuter attribute:NSLayoutAttributeCenterY relateBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY .......]];

to center align things.

The above type of "relational constraints" (it's what I personally call them) is what I tend to use for specifying relations between two views eg center alignment, relative positioning.

Visual Formatting language on the other hand is more useful for pinning views to each other from my own observation.

Here's a demo app:

ViewController.h

@interface ViewController : UIViewController

@property (nonatomic, strong) UIView *outerView;
@property (nonatomic, strong) UIView *innerView;

@property (nonatomic, strong) NSLayoutConstraint *outerViewHeightConstraint;

@end

ViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [self initViews];
    [self initConstraints];


    // change height of outerView after 3 seconds
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        [self changeHeight];

    });
}

-(void)changeHeight
{
    self.outerViewHeightConstraint.constant = 150;

    [UIView animateWithDuration:1.0 animations:^{
        [self.innerView layoutIfNeeded];
        [self.view layoutIfNeeded];
    }];
}

-(void)initViews
{
    self.outerView = [[UIView alloc] init];
    self.outerView.backgroundColor = [UIColor purpleColor];

    self.innerView = [[UIView alloc] init];
    self.innerView.backgroundColor = [UIColor redColor];

    [self.outerView addSubview:self.innerView];

    [self.view addSubview:self.outerView];
}

-(void)initConstraints
{
    self.outerView.translatesAutoresizingMaskIntoConstraints = NO;
    self.innerView.translatesAutoresizingMaskIntoConstraints = NO;

    id views = @{
                 @"outerView": self.outerView,
                 @"innerView": self.innerView
                 };

    // outer view constraints
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[outerView(300)]" options:0 metrics:nil views:views]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.outerView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.outerView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];

    // give outerView a default height e.g. 300
    // note we can animate the height of outerview later using this var
    self.outerViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self.outerView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1.0 constant:300.0];

    [self.view addConstraint:self.outerViewHeightConstraint];



    // inner view constraints
    [self.outerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[innerView]-10-|" options:0 metrics:nil views:views]];
    [self.outerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[innerView(50)]" options:0 metrics:nil views:views]];

    [self.outerView addConstraint:[NSLayoutConstraint constraintWithItem:self.innerView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.outerView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];

    [self.outerView addConstraint:[NSLayoutConstraint constraintWithItem:self.innerView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.outerView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];
}

After running the app for 3 seconds, you'll see the outer view (purple view) shrink in height while the red inner view remains centered within the purple view and maintains its height.

屏幕截图1屏幕截图2

You can also rotate the view too.

屏幕截图3

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