iOS_autoLayout_Masonry
概述
Masonry是一个轻量级的布局框架与更好的包装AutoLayout语法。
Masonry有它自己的布局方式,描述NSLayoutConstraints使布局代码更简洁易读。
Masonry支持iOS和Mac OS X。
Masonry github 地址:https://github.com/SnapKit/Masonry
对比
使用NSLayoutConstraints创建约束
@interface contrastViewController() @property (nonatomic,strong) UIView *myView; @end @implementation contrastViewController -(void)loadView { [super loadView]; _myView = [[UIView alloc]init]; [self.view addSubview:_myView]; } -(void)viewDidLoad { [super viewDidLoad]; _myView.backgroundColor = [UIColor orangeColor]; _myView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addConstraints:@[ [NSLayoutConstraint constraintWithItem:_myView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:10], [NSLayoutConstraint constraintWithItem:_myView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:10], [NSLayoutConstraint constraintWithItem:_myView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-10], [NSLayoutConstraint constraintWithItem:_myView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1 constant:-10], ]]; } @end
即使这样一个简单的示例,所需的代码量也要非常冗长;
另一个选择是使用视图形式语言(VFL),这个少一点啰嗦;然而ASCLL类型语法有其自身的缺陷,也有些约束难以实现;
使用Masonry创建相同的约束
@interface contrastViewController() @property (nonatomic,strong) UIView *myView; @end @implementation contrastViewController -(void)loadView { [super loadView]; _myView = [[UIView alloc]init]; [self.view addSubview:_myView]; } -(void)viewDidLoad { [super viewDidLoad]; _myView.backgroundColor = [UIColor orangeColor]; [_myView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view).offset(10); // 相对于self.view 顶部 10 make.left.equalTo(self.view).offset(10); // 相对于self.view 左边 10 make.bottom.equalTo(self.view).offset(-10); // 相对于self.view 底部 -10 make.right.equalTo(self.view).offset(-10); // 相对于self.view 右边 -10 }]; } @end
还可以更简洁
@interface contrastViewController() @property (nonatomic,strong) UIView *myView; @end @implementation contrastViewController -(void)loadView { [super loadView]; _myView = [[UIView alloc]init]; [self.view addSubview:_myView]; } -(void)viewDidLoad { [super viewDidLoad]; _myView.backgroundColor = [UIColor orangeColor]; UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10); [_myView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.view).insets(padding); }]; } @end
还要注意在第一个例子中我们必须添加约束到self.view,_myView.translatesAutoresizingMaskIntoConstraints = NO;
然而Masonry将自动添加约束到适当的视图_myView.translatesAutoresizingMaskIntoConstraints = NO;
示例
示例 00
@interface _00_BasicViewController () @property (nonatomic) UIView *greenView; @end @implementation _00_BasicViewController -(void)loadView { [super loadView]; _greenView = [[UIView alloc]init]; [self.view addSubview:_greenView]; } - (void)viewDidLoad { [super viewDidLoad]; _greenView.backgroundColor = [UIColor greenColor]; [_greenView mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(CGSizeMake(200, 200)); // 设置大小 make.center.equalTo(self.view); // 居中显示 }]; } @end
示例01
@interface _01_BasicViewController () @property (nonatomic,strong) UIView *greenView; @property (nonatomic,strong) UIView *redView; @property (nonatomic,strong) UIView *blueView; @end @implementation _01_BasicViewController -(void)loadView { [super loadView]; _greenView = [[UIView alloc]init]; _redView = [[UIView alloc]init]; _blueView = [[UIView alloc]init]; [self.view addSubview:_greenView]; [self.view addSubview:_redView]; [self.view addSubview:_blueView]; } - (void)viewDidLoad { [super viewDidLoad]; [_greenView setBackgroundColor:[UIColor greenColor]]; [_redView setBackgroundColor:[UIColor redColor]]; [_blueView setBackgroundColor:[UIColor blueColor]]; [self.greenView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view).offset(10); // 顶 等于 View 顶 +10 make.left.equalTo(self.view).offset(10); // 左 等于 View 左 +10 make.bottom.equalTo(_blueView.mas_top).offset(-10); // 底 等于 蓝色 顶 -10 make.right.equalTo(_redView.mas_left).offset(-10); // 右 等于 红色 右 -10 make.width.equalTo(_redView); // 宽 等于 红色 宽 make.height.equalTo(_redView); // 高 等于 红色 高 make.height.equalTo(_blueView); // 高 等于 蓝色 高 }]; [self.redView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_greenView); // 顶 等于 绿色 顶 make.left.equalTo(_greenView.mas_right).offset(10); // 左 等于 绿色 右 +10 make.bottom.equalTo(_greenView); // 底 等于 绿色 底 make.right.equalTo(self.view).offset(-10); // 右 等于 View 右 -10 make.width.equalTo(_greenView); // 宽 等于 绿色 宽 make.height.equalTo(_greenView); // 高 等于 绿色 高 }]; [self.blueView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_greenView.mas_bottom).offset(10); // 顶 等于 绿色 底 +10 make.left.equalTo(self.view).offset(10); // 左 等于 View 左 +10 make.bottom.equalTo(self.view).offset(-10); // 底 等于 View 底 -10 make.right.equalTo(self.view).offset(-10); // 右 等于 View 右 -10 make.height.equalTo(_greenView); // 高 等于 绿色 高 }]; } @end
示例02
@interface _02_Update_ConstraintsViewController () @property (nonatomic,strong) UIButton *button; @property (nonatomic,assign) CGSize buttonSize; @end @implementation _02_Update_ConstraintsViewController -(void)loadView { [super loadView]; _button = [UIButton buttonWithType:UIButtonTypeSystem]; [self.view addSubview:_button]; } - (void)viewDidLoad { [super viewDidLoad]; [_button setTitle:@"点击" forState:UIControlStateNormal]; [_button.layer setBorderColor:[[UIColor greenColor] CGColor]]; [_button.layer setBorderWidth:3]; [_button addTarget:self action:@selector(clickWithButton:) forControlEvents:UIControlEventTouchUpInside]; _buttonSize = CGSizeMake(100, 100); [self.view setNeedsUpdateConstraints]; } - (void)updateViewConstraints { [self.button mas_updateConstraints:^(MASConstraintMaker *make) {// 更新约束 make.center.equalTo(self.view); // 居中 make.width.equalTo(@(_buttonSize.width)).priorityLow(); // 宽 等于 100 优先级 低 第一次显示的时候是100 make.height.equalTo(@(_buttonSize.height)).priorityLow(); // 高 等于 100 优先级 低 第一次显示的时候是100 make.width.lessThanOrEqualTo(self.view); // 宽 小于 等于 view 当宽度大于等于 view 需满足此条件 make.height.lessThanOrEqualTo(self.view); // 高 小于 等于 view 当高度大于等于 view 需满足此条件 }]; [super updateViewConstraints]; } - (void)clickWithButton:(UIButton *)button { _buttonSize = CGSizeMake(_buttonSize.width * 1.3, _buttonSize.height * 1.3); // 宽高 乘 1.3 [self.view setNeedsUpdateConstraints]; [UIView animateWithDuration:0.4 animations:^{ [self.view layoutIfNeeded]; }]; } @end
示例03
@interface _03_Remake_ConstraintsViewController () @property (nonatomic, strong) UIButton *movingButton; @property (nonatomic, assign) BOOL topLeft; @end @implementation _03_Remake_ConstraintsViewController -(void)loadView { [super loadView]; _movingButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.view addSubview:_movingButton]; } - (void)viewDidLoad { [super viewDidLoad]; [_movingButton setTitle:@"点击" forState:UIControlStateNormal]; _movingButton.layer.borderColor = UIColor.greenColor.CGColor; _movingButton.layer.borderWidth = 3; [_movingButton addTarget:self action:@selector(clickWithButton:) forControlEvents:UIControlEventTouchUpInside]; self.topLeft = YES; [self.view setNeedsUpdateConstraints]; } + (BOOL)requiresConstraintBasedLayout { return YES; } - (void)updateViewConstraints { // 重置约束 会把已有的约束删除重新添加 [self.movingButton mas_remakeConstraints:^(MASConstraintMaker *make) { make.width.equalTo(@(100)); make.height.equalTo(@(100)); if (self.topLeft) { make.left.equalTo(self.view).offset(10); make.top.equalTo(self.view).offset(10); } else { make.bottom.equalTo(self.view).offset(-10); make.right.equalTo(self.view).offset(-10); } }]; [super updateViewConstraints]; } - (void)clickWithButton:(UIButton *)button { self.topLeft = !self.topLeft; [self.view setNeedsUpdateConstraints]; [self.view updateConstraintsIfNeeded]; [UIView animateWithDuration:0.4 animations:^{ [self.view layoutIfNeeded]; }]; } @end
示例04
@interface _04_Using_ConstantsViewController () @property (nonatomic,strong) UIView *purpleView; @property (nonatomic,strong) UIView *orangeView; @end @implementation _04_Using_ConstantsViewController -(void)loadView { [super loadView]; self.purpleView = [[UIView alloc]init]; self.orangeView = [[UIView alloc]init]; [self.view addSubview:_purpleView]; [self.view addSubview:_orangeView]; } - (void)viewDidLoad { [super viewDidLoad]; self.purpleView.backgroundColor = UIColor.purpleColor; self.orangeView.backgroundColor = UIColor.orangeColor; [self.purpleView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(@20); // 顶 20 相对于self.View make.left.equalTo(@20); // 左 20 make.bottom.equalTo(@-20); // 底 -20 make.right.equalTo(@-20); // 右 -20 }]; [self.orangeView mas_makeConstraints:^(MASConstraintMaker *make) { make.center.mas_equalTo(CGPointMake(0, 50)); // 中心点Y 相对于self.View Y 50 make.size.mas_equalTo(CGSizeMake(200, 100)); // 大小 200 100 }]; } @end
示例05
@interface _05_Composite_EdgesViewController () @end @implementation _05_Composite_EdgesViewController -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; UIView *lastView = self.view; for (int i = 0; i < 10; i++) { UIView *view = [[UIView alloc]init]; view.backgroundColor = [self randomColor]; [self.view addSubview:view]; [view mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(lastView).insets(UIEdgeInsetsMake(5, 10, 15, 20));//相对于上一个View 5 10 -15 -20 }]; lastView = view; } } - (UIColor *)randomColor { CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0 CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1]; } @end
示例06
@interface _06_Aspect_FitViewController () @property (nonatomic,strong) UIView *topView; @property (nonatomic,strong) UIView *topInnerView; @property (nonatomic,strong) UIView *bottomView; @property (nonatomic,strong) UIView *bottomInnerView; @end @implementation _06_Aspect_FitViewController -(void)loadView { [super loadView]; self.topView = [[UIView alloc] init]; self.topInnerView = [[UIView alloc] init]; self.bottomView = [[UIView alloc] init]; self.bottomInnerView = [[UIView alloc] init]; [self.view addSubview:_topView]; [self.view addSubview:_topInnerView]; [self.view addSubview:_bottomView]; [self.view addSubview:_bottomInnerView]; } - (void)viewDidLoad { [super viewDidLoad]; self.topView.backgroundColor = [UIColor redColor]; self.bottomView.backgroundColor = [UIColor blueColor]; self.topInnerView.backgroundColor = [UIColor greenColor]; self.bottomInnerView.backgroundColor = [UIColor grayColor]; [self.topView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.and.top.equalTo(self.view); // 左边、右边、顶部 等于 self.View }]; [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.and.bottom.equalTo(self.view); // 左边、右边、底部 等于 self.View make.top.equalTo(self.topView.mas_bottom); // 顶部 等于 topView 的 底部 make.height.equalTo(self.topView); // 高 等于 topView // 结果:上下55分成 }]; [self.topInnerView mas_makeConstraints:^(MASConstraintMaker *make) { make.width.equalTo(self.topInnerView.mas_height).multipliedBy(3); // 宽度是高度的3倍 make.width.and.height.lessThanOrEqualTo(self.topView); // 宽度、高度 小于 topView的宽度高度 make.width.and.height.equalTo(self.topView).with.priorityLow(); // 宽度、高度 等于 topView的宽度高度 优先级 低 make.center.equalTo(self.topView); // 中心点位置 等于 topView }]; [self.bottomInnerView mas_makeConstraints:^(MASConstraintMaker *make) { make.height.equalTo(self.bottomInnerView.mas_width).multipliedBy(3);// 高度是宽度的3倍 make.width.and.height.lessThanOrEqualTo(self.bottomView); // 宽度、高度 小于 bottomView的宽度高度 make.width.and.height.equalTo(self.bottomView).with.priorityLow(); // 宽度、高度 等于 bottonView的宽度高度 优先级 低 make.center.equalTo(self.bottomView); // 中心点位置 等于 bottonView }]; } @end
示例07
@interface _07_Basic_AnimatedViewController () @property (nonatomic,strong) UIView *greenView; @property (nonatomic,strong) UIView *redView; @property (nonatomic,strong) UIView *blueView; @property (nonatomic,assign) NSInteger padding; @property (nonatomic, assign) BOOL animating; @property (nonatomic, strong) NSMutableArray *animatableConstraints; @end @implementation _07_Basic_AnimatedViewController -(void)loadView { [super loadView]; self.greenView = [[UIView alloc]init]; self.redView = [[UIView alloc]init]; self.blueView = [[UIView alloc]init]; [self.view addSubview:self.greenView]; [self.view addSubview:self.redView]; [self.view addSubview:self.blueView]; } - (void)viewDidLoad { [super viewDidLoad]; _greenView.backgroundColor = UIColor.greenColor; _redView.backgroundColor = UIColor.redColor; _blueView.backgroundColor = UIColor.blueColor; NSInteger padding = self.padding = 10; _animatableConstraints = [NSMutableArray array]; UIEdgeInsets paddingInsets = UIEdgeInsetsMake(_padding,_padding,_padding,_padding); // 一开始 green,red,blue的尺寸 再通过约束来改变 [_greenView mas_makeConstraints:^(MASConstraintMaker *make) { // 添加约束的同时添加到数组 [_animatableConstraints addObjectsFromArray:@[ make.edges.equalTo(self.view).insets(paddingInsets).priorityLow(), // 优先级低 make.bottom.equalTo(_blueView.mas_top).offset(-padding), // green bottom 相对 blue top -10 ]]; make.size.equalTo(_redView); // 大小 = redView make.height.equalTo(_blueView); // 高 = blue }]; [_redView mas_makeConstraints:^(MASConstraintMaker *make) { // 添加约束的同时添加到数组 [_animatableConstraints addObjectsFromArray:@[ make.edges.equalTo(self.view).insets(paddingInsets).priorityLow(), // 优先级低 make.left.equalTo(_greenView.mas_right).offset(padding), // left 红色 green right 10 make.bottom.equalTo(_blueView.mas_top).offset(-padding), // bottom 蓝色 top -10 ]]; make.size.equalTo(_greenView); // 大小 = green make.height.equalTo(_blueView.mas_height); // 高 = blue }]; [_blueView mas_makeConstraints:^(MASConstraintMaker *make) { // 添加约束的同时添加到数组 [self.animatableConstraints addObjectsFromArray:@[ make.edges.equalTo(self.view).insets(paddingInsets).priorityLow(), // 优先级低 ]]; make.height.equalTo(_greenView); }]; [self.view layoutIfNeeded]; // 可以注释此部分,查看没有动画时的效果 if (self.view) { _animating = YES; [self animateWithInvertedInsets:NO]; } } - (void)animateWithInvertedInsets:(BOOL)invertedInsets { if (!_animating) return; // 是否需要动画 NSInteger padding = invertedInsets ? 100 : _padding; // Yes 就缩小100 否 10 UIEdgeInsets paddingInsets = UIEdgeInsetsMake(padding, padding, padding, padding); for (MASConstraint *constraint in _animatableConstraints) { constraint.insets = paddingInsets; } [UIView animateWithDuration:1 animations:^{ [self.view layoutIfNeeded]; } completion:^(BOOL finished) { [self animateWithInvertedInsets:!invertedInsets]; // 取相反值无限循环执行动画 }]; } @end
示例08
@interface _08_Bacony_LabelsViewController () @property (nonatomic,strong) UILabel *longLabel; @property (nonatomic,strong) UILabel *shortLabel; @property (nonatomic,strong) UILabel *contentLable; @end @implementation _08_Bacony_LabelsViewController - (void)loadView { [super loadView]; _longLabel = [[UILabel alloc]init]; _shortLabel = [[UILabel alloc]init]; _contentLable = [[UILabel alloc]init]; [self.view addSubview:_longLabel]; [self.view addSubview:_shortLabel]; [self.view addSubview:_contentLable]; } - (void)viewDidLoad { [super viewDidLoad]; self.title = @"08_Bacony Labels"; _longLabel.numberOfLines = 0; _longLabel.font =[UIFont systemFontOfSize:13]; _longLabel.backgroundColor = [UIColor redColor]; _longLabel.textColor = [UIColor darkGrayColor]; _longLabel.lineBreakMode = NSLineBreakByTruncatingTail; _longLabel.text = @"Bacon ipsum dolor sit amet spare ribs fatback kielbasa salami, tri-tip jowl pastrami flank short loin rump sirloin. Tenderloin frankfurter chicken biltong rump chuck filet mignon pork t-bone flank ham hock."; _shortLabel.numberOfLines = 1; _shortLabel.textColor = [UIColor purpleColor]; _shortLabel.backgroundColor = [UIColor yellowColor]; _shortLabel.lineBreakMode = NSLineBreakByTruncatingTail; _shortLabel.text = @"Bacon"; _contentLable.numberOfLines = 0; _contentLable.font =[UIFont systemFontOfSize:13]; _contentLable.backgroundColor = [UIColor greenColor]; _contentLable.textColor = [UIColor darkGrayColor]; _contentLable.lineBreakMode = NSLineBreakByTruncatingTail; _contentLable.text = @"枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客枫子的博客"; // 只设置left top [_longLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.view).offset(10); make.top.equalTo(self.view).offset(10); }]; // 只设置 centerY right [_shortLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(_longLabel); // make.right.equalTo(self.view).offset(-10); }]; // top left right 根据文字多少自动计算高度 [_contentLable mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_longLabel.mas_bottom).offset(10); make.left.equalTo(@10); make.right.equalTo(self.view).offset(-10); }]; } -(void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; CGFloat width = CGRectGetMinX(self.shortLabel.frame)-10; width -= CGRectGetMinX(self.longLabel.frame); self.longLabel.preferredMaxLayoutWidth = width; } @end
示例09
@interface _09_UIScrollViewViewController () @property (nonatomic,strong) UIScrollView *scrollView; @property (nonatomic,strong) UIView *contentView; @end @implementation _09_UIScrollViewViewController -(void)loadView { [super loadView]; _scrollView = [[UIScrollView alloc]init]; _contentView = [[UIView alloc]init]; [self.view addSubview:_scrollView]; [self.scrollView addSubview:_contentView]; } - (void)viewDidLoad { [super viewDidLoad]; self.title = @"09_UIScrollView"; _scrollView.backgroundColor = [UIColor grayColor]; [_scrollView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.view); // self.view一样大小 }]; _contentView.backgroundColor = [UIColor greenColor]; [_contentView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(_scrollView); // 大小 = _scrollView make.width.equalTo(_scrollView); // width = _scrollView }]; UIView *lastView; CGFloat height = 25; for (int i = 0; i < 10; i++) { UIView *view = [[UIView alloc]init]; view.backgroundColor = [self randomColor]; [_contentView addSubview:view]; // 点击 改变透明度 UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)]; [view addGestureRecognizer:singleTap]; [view mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(lastView ? lastView.mas_bottom : @0); // 第一个View top = 0; make.left.equalTo(@0); // left 0 make.width.equalTo(_contentView); // width = _contentView; make.height.equalTo(@(height)); // heinght = height }]; height += 25; // += 25; lastView = view; } [_contentView mas_makeConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(lastView); // bottom = lastView }]; } - (UIColor *)randomColor { CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0 CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1]; } - (void)singleTap:(UITapGestureRecognizer*)sender { [sender.view setAlpha:sender.view.alpha / 1.20]; // To see something happen on screen when you tap :O [self.scrollView scrollRectToVisible:sender.view.frame animated:YES]; };
示例10
static CGFloat const kArrayExampleIncrement = 10.0; @interface _10_ArrayViewController () @property (nonatomic,strong) UIView *line; @property (nonatomic,strong) UIButton *raiseButton; @property (nonatomic,strong) UIButton *centerButton; @property (nonatomic,strong) UIButton *lowerButton; @property (nonatomic, assign) CGFloat offset; @property (nonatomic, strong) NSArray *buttonViews; @end @implementation _10_ArrayViewController -(void)loadView { [super loadView]; _line = [[UIView alloc]init]; _raiseButton = [UIButton buttonWithType:UIButtonTypeSystem]; _centerButton = [UIButton buttonWithType:UIButtonTypeSystem]; _lowerButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.view addSubview:_line]; [self.view addSubview:_raiseButton]; [self.view addSubview:_centerButton]; [self.view addSubview:_lowerButton]; } - (void)viewDidLoad { [super viewDidLoad]; _line.backgroundColor = [UIColor redColor]; [_raiseButton setTitle:@"Raise" forState:UIControlStateNormal]; [_centerButton setTitle:@"Center" forState:UIControlStateNormal]; [_lowerButton setTitle:@"Lower" forState:UIControlStateNormal]; [_raiseButton addTarget:self action:@selector(raiseAction) forControlEvents:UIControlEventTouchUpInside]; [_centerButton addTarget:self action:@selector(centerAction) forControlEvents:UIControlEventTouchUpInside]; [_lowerButton addTarget:self action:@selector(lowerAction) forControlEvents:UIControlEventTouchUpInside]; // 添加跟中线,方便查看按钮的移动 [_line mas_makeConstraints:^(MASConstraintMaker *make) { make.width.equalTo(self.view); make.height.equalTo(@1); make.center.equalTo(self.view); }]; [_raiseButton mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.view).with.offset(10.0); }]; [_centerButton mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self.view); }]; [_lowerButton mas_makeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(self.view).with.offset(-10); }]; self.buttonViews = @[_raiseButton, _lowerButton, _centerButton]; } - (void)centerAction { self.offset = 0.0; } - (void)raiseAction { self.offset -= kArrayExampleIncrement; } - (void)lowerAction { self.offset += kArrayExampleIncrement; } - (void)setOffset:(CGFloat)offset { _offset = offset; [self.view setNeedsUpdateConstraints]; [UIView animateWithDuration:0.2 animations:^{ [self.view layoutIfNeeded]; }]; } - (void)updateViewConstraints { // 同时更新多个按钮的约束 [self.buttonViews mas_updateConstraints:^(MASConstraintMaker *make) { make.baseline.equalTo(self.view.mas_centerY).with.offset(self.offset); // buttonViews的底线 }]; [super updateViewConstraints]; } @end
示例11
@interface _11_Attribute_ChainingViewController () @property (nonatomic,strong) UIView *greenView; @property (nonatomic,strong) UIView *redView; @property (nonatomic,strong) UIView *blueView; @end @implementation _11_Attribute_ChainingViewController -(void)loadView { [super loadView]; _greenView = [[UIView alloc]init]; _redView = [[UIView alloc]init]; _blueView = [[UIView alloc]init]; [self.view addSubview:_greenView]; [self.view addSubview:_redView]; [self.view addSubview:_blueView]; } - (void)viewDidLoad { [super viewDidLoad]; UIEdgeInsets padding = UIEdgeInsetsMake(15, 10, 15, 10); _greenView.backgroundColor = UIColor.greenColor; [_greenView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.and.left.equalTo(self.view).insets(padding); // 顶部15 左边 10 make.bottom.equalTo(_blueView.mas_top).insets(padding); // 底部与蓝色 15 make.width.equalTo(_redView.mas_width); // 宽度与红色相等 make.height.equalTo(@[_redView, _blueView]); // 高度与红蓝相等 }]; _redView.backgroundColor = UIColor.redColor; [_redView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.and.right.equalTo(self.view).insets(padding); // 顶部15 右边 10 make.left.equalTo(_greenView.mas_right).insets(padding);// 左边与绿色 10 make.bottom.equalTo(_blueView.mas_top).insets(padding); // 底部与蓝色 15 make.width.equalTo(_greenView.mas_width); // 宽度与红色相等 make.height.equalTo(@[_greenView, _blueView]); // 高度与绿蓝相等 }]; _blueView.backgroundColor = UIColor.blueColor; [_blueView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_greenView.mas_bottom).insets(padding); // 顶部绿色 15 make.left.right.and.bottom.equalTo(self.view).insets(padding); // 左边 10 右边 10 底部 15 make.height.equalTo(@[_greenView, _redView]); // 高度与红绿相等 }]; } @end
示例12
@interface _12_Layout_GuidesViewController () @property (nonatomic,strong) UIView *topView; @property (nonatomic,strong) UIView *bottomView; @end @implementation _12_Layout_GuidesViewController -(void)loadView { [super loadView]; _topView = [[UIView alloc]init]; _bottomView = [[UIView alloc]init]; [self.view addSubview:_topView]; [self.view addSubview:_bottomView]; } - (void)viewDidLoad { [super viewDidLoad]; _topView.backgroundColor = UIColor.greenColor; [_topView mas_makeConstraints:^(MASConstraintMaker *make) { UIView *topLayoutGuide = (id)self.topLayoutGuide; //显示屏幕内容的垂直程度最高,使用自动布局的约束。(只读) make.top.equalTo(topLayoutGuide.mas_bottom); make.left.equalTo(self.view); make.right.equalTo(self.view); make.height.equalTo(@40); }]; _bottomView.backgroundColor = UIColor.redColor; [_bottomView mas_makeConstraints:^(MASConstraintMaker *make) { UIView *bottomLayoutGuide = (id)self.bottomLayoutGuide; make.bottom.equalTo(bottomLayoutGuide.mas_top); make.left.equalTo(self.view); make.right.equalTo(self.view); make.height.equalTo(@40); }]; } @end