简体   繁体   中英

Adding auto-layout constraints to subviews of a view with Masonry

I am using the Masonry iOS library to simplify some of the logic around iOS autolayout and have loved it thus far. Just recently, though, I'm working in a more complex app and attempting to add auto-layout constraints to subviews related to their parent views. Doing this, however, seems to force the parent view to adopt the constraints of it's children. It may be that I'm just not fully understanding this aspect of auto-layout inheritance, but here's a simple example:

UIView *test = UIView.new;
[test setBackgroundColor:[UIColor orangeColor]];
[self.view addSubview:test];
[test makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
}];

UIView *test2 = UIView.new;
[test2 setBackgroundColor:[UIColor redColor]];
[test addSubview:test2];
[test2 makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(test).with.insets(UIEdgeInsetsMake(5, 5, 5, 5));
    make.centerX.equalTo(test);
}];

In this example, in spite of the second UIView (test2) being a subview of test and having it's edges set to match test, when this code is run the "test" view is shoved to be flush left with the screen. Oddly the top and bottom seem to respect the edges inset of the "test" view and they position themselves accurately however the right edge of "view" now sits at 20 points inset (since left get pulled flush with the left side).

Now if I alter test2 and make it a subview of self.view instead of a subview of test the constraints suddenly work fine.

Here's a visual picture of what is happening when test2 is a subview of test:

一切都被冲走了

What this seems to imply is that you can only add related constraints to children of the same parent view. I know this can't be the case, but in spite of trying a variety of different things I cannot seem to keep the deeper subviews from impacting their parents.

In my case it turns out that the cause of the issue was a constraint placed on the view controller's base view. That constraint, originally meant to simply position the base view at full width and height, was indeed setting a width, a height and a top position but no left position.

Leaving the left position unconstrained to anything caused future subviews, who themselves included a left constraint, to push the parent view around to conform to the subview constraints.

The lesson here: Start at the VERY beginning of your view stack and validate each of your subviews along the way before assuming the issue is with your subviews.

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