Painted painted levels: fostered fostered fostered

Tags: “iOS AutoLayout” “iOS AutoLayout” “NSLayoutConstraint

When I shared the automatic layout of iOS UIButton according to the content in Mulinlo offline, I discussed the common layout mode of iOS with my front-end classmates. The discussion process is very lively and not easy to record, but the author thinks it is necessary to record the results of the discussion, hoping to help some students.

The author classifies the most popular iOS layouts into Frame, Autoresizing, Constraint, StackView, and navigation, and explains them one by one. This article introduces Constraint.

Constraint is a more flexible and powerful alternative to Autoresizing. The short name for Constraint is NSLayoutConstraint, also known as AutoLayout, which makes it very easy to build pages with storyboards. For example, NSLayoutConstraint solves problems between peer views that the authors didn’t implement in the previous article, and no code is required. The constraints built into the Storyboard are as follows.

Of course, developers can also leverage the NSLayoutConstraint layout view in code form. For example, the author added a light gray contentView subView5 in cyanColor to the 4-bisect contentView, making it always display at a fixed width, as shown below.

The code to achieve the above effect is as follows.

- (void)viewDidLoad { [super viewDidLoad]; UIView *subView5 = [[UIView alloc] initWithFrame:CGRectZero]; subView5.backgroundColor = [[UIColor cyanColor] colorWithAlphaComponent:.6]; subView5.translatesAutoresizingMaskIntoConstraints = NO; [_contentView addSubview:subView5]; NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:subView5 attribute:NSLayoutAttributeWidth RelatedBy: NSLayoutRelationEqual toItem: nil attribute: NSLayoutAttributeNotAnAttribute multiplier: 1.0 constant: 100.0]; NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:subView5 attribute:NSLayoutAttributeHeight RelatedBy: NSLayoutRelationEqual toItem: nil attribute: NSLayoutAttributeNotAnAttribute multiplier: 1.0 constant: 200.0]; NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:subView5 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_contentView Attribute: NSLayoutAttributeCenterX multiplier: 1.0 constant: 0]; NSLayoutConstraint *centerYConstraint = [NSLayoutConstraint constraintWithItem:subView5 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:_contentView Attribute: NSLayoutAttributeCenterY multiplier: 1.0 constant: 0]; [_contentView addConstraints:@[widthConstraint, heightConstraint, centerXConstraint, centerYConstraint]]; }Copy the code

With the code above, take a look at the use of the NSLayoutConstraint. First, when using code to leverage the NSLayoutConstraint layout view, specify that the view is not controlled by Autoresizing (code below). Otherwise, constraints conflict.

subView5.translatesAutoresizingMaskIntoConstraints = NO;
Copy the code

The constraint view is then done through two steps: Set constraints and Add constraints.

Set constraints

NSLayoutConstraint has a standard API for setting constraints, as follows.

/* Create constraints explicitly.  Constraints are of the form "view1.attr1 = view2.attr2 * multiplier + constant" 
 If your equation does not have a second view and attribute, use nil and NSLayoutAttributeNotAnAttribute.
 */
+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
Copy the code

To give a simple explanation of the above API, do c constraints on the attr1 attribute of view1 and attr2 attribute of view2 using relation and multiplier. For example, the constraint view1 and view2 can be written like this:

[NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual ToItem: view2 attribute: NSLayoutAttributeWidth multiplier: 1.0 constant: 0];Copy the code

Attr1 and attr2 are both values from the NSLayoutAttribute enumeration.

typedef NS_ENUM(NSInteger, NSLayoutAttribute) {
    NSLayoutAttributeLeft = 1,
    NSLayoutAttributeRight,
    NSLayoutAttributeTop,
    NSLayoutAttributeBottom,
    NSLayoutAttributeLeading,
    NSLayoutAttributeTrailing,
    NSLayoutAttributeWidth,
    NSLayoutAttributeHeight,
    NSLayoutAttributeCenterX,
    NSLayoutAttributeCenterY,
    NSLayoutAttributeLastBaseline,
    NSLayoutAttributeBaseline NS_SWIFT_UNAVAILABLE("Use 'lastBaseline' instead") = NSLayoutAttributeLastBaseline,
    NSLayoutAttributeFirstBaseline NS_ENUM_AVAILABLE_IOS(8_0),
    
    NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
    
    NSLayoutAttributeNotAnAttribute = 0
};
Copy the code

Relation is evaluated from the NSLayoutRelation enumeration.

typedef NS_ENUM(NSInteger, NSLayoutRelation) {
    NSLayoutRelationLessThanOrEqual = -1,
    NSLayoutRelationEqual = 0,
    NSLayoutRelationGreaterThanOrEqual = 1,
};
Copy the code

In summary, the four constraints of subView5 will be easier to read once you understand the meanings of the API parameters.

Adding constraints

Take a look at the code that adds the constraint in the example below.

[_contentView addConstraints:@[widthConstraint, heightConstraint, centerXConstraint, centerYConstraint]];
Copy the code

The author adds all four constraints to the contentView, and of course, the implementation proves that this is ok. But some students asked, “Since the location of subView5 is constrained to the contentView, it makes sense that centerXConstraint and centerYConstraint were added to the contentView, But widthConstraint and heightConstraint are only related to subView5. Why should they be added to contentView?” . Yes, in that sense, adding widthConstraints and heightconstraints to subView5 was easier to understand, so the authors made the following changes.

[subView5 addConstraints:@[widthConstraint, heightConstraint]];
[_contentView addConstraints:@[centerXConstraint, centerYConstraint]];
Copy the code

There is no problem from the operation effect after modification. The reason why all four constraints are added to the contentView is that ** No matter which view constraints are added to that view, its superview, or its higher-level superview, there is no problem. ** Therefore, in programming, developers often add multiple constraints to a superview that is close to the user.

The implementation details for this article can be viewed in QiLayoutDemo.


Recommended articles:

IOS UIButton automatically layouts based on content iOS specified initialization method hitTest method in UIView