Object-C :使用Masonry
Swift:使用Snapkit
Masonry 和 布局优先级约束
呆萌的中指
实例一:
masonary:约束优先级
#pragma mark - 基础使用1
- (void)firestExample{
//红
[_redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.view.mas_left).with.offset(20);
make.bottom.mas_equalTo(self.view.mas_bottom).with.offset(-80);
make.height.equalTo(@50);
}];
//蓝
[_blueView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(_redView.mas_right).with.offset(40);
make.height.width.bottom.mas_equalTo(_redView);
}];
//黄
[_yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(_blueView.mas_right).with.offset(40);
make.right.mas_equalTo(self.view.mas_right).with.offset(-20);
make.height.width.bottom.mas_equalTo(_redView);
//优先级
//必须添加这个优先级,否则blueView被移除后,redView 和 yellowView 的宽度就不能计算出来
make.left.mas_equalTo(_redView.mas_right).with.offset(20).priority(250);
}];
[NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(removeBlueView:) userInfo:_blueView repeats:YES];
}
- (void)removeBlueView:(NSTimer *)timer{
UIView *view = timer.userInfo;
[view removeFromSuperview];
[UIView animateWithDuration:0.3 animations:^{
[self.view layoutIfNeeded];
}];
}
实例二:
masonry:基本方法
#pragma mark - 基础使用2
- (void)secondExample{
int padding = 15;
[_redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.view.mas_left).with.offset(padding);
make.top.mas_equalTo(self.view.mas_top).with.offset(padding);
make.bottom.mas_equalTo(_yellowView.mas_top).with.offset(-padding);
make.width.mas_equalTo(_blueView);
}];
[_blueView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(_redView.mas_right).with.offset(padding);
make.right.mas_equalTo(self.view.mas_right).with.offset(-padding);
make.height.bottom.mas_equalTo(_redView);
}];
[_yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.view.mas_left).with.offset(padding);
make.right.mas_equalTo(self.view.mas_right).with.offset(-padding);
make.bottom.mas_equalTo(self.view.mas_bottom).with.offset(-padding);
make.height.mas_equalTo(_redView);
}];
}
实例三:
masonry : 更新约束
#pragma mark - 点击按钮放大
- (void)growButtonClick{
self.growButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.growButton setTitle:@"点我放大" forState:UIControlStateNormal];
self.growButton.layer.borderColor = [UIColor greenColor].CGColor;
self.growButton.layer.borderWidth = 3;
[self.growButton addTarget:self action:@selector(Click:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.growButton];
self.scacle = 1.0;
[self.growButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self.view);
//初始化宽,高,优先级最低
make.width.height.mas_equalTo(100*self.scacle);
//最大放大到整个view
make.width.height.lessThanOrEqualTo(self.view);
}];
}
- (void)Click:(UIButton *)sender{
self.scacle += 1.0;
//告诉self.view 约束需要更新
[self.view setNeedsUpdateConstraints];
//调用此方法self.view监测是否需要更新约束,若需要则更新,下面添加动画效果才起作用
[self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:0.3 animations:^{
[self.view layoutIfNeeded];
}];
}
//重写该方法来更新约束
- (void)updateViewConstraints{
//对于已经定义过的约束,需要更改的话,只能是使用update的方法修改才有效
[self.growButton mas_updateConstraints:^(MASConstraintMaker *make) {
//这里写需要更新的约束,不用更新的约束将继续存在
//不会取代,如:其宽高小于屏幕宽高不需要重新再约束
make.width.height.mas_equalTo(100*self.scacle);
}];
[super updateViewConstraints];
}
实例四:
masonry :重写约束
#pragma mark - 收缩
/*
注意:multipliedBy必须是对同一个控件本身,如果修改成相对其他控件会导致Crash
*/
- (void)createExpandButton{
self.isExpanded = NO;
self.growButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.growButton setTitle:@"点我展开" forState:UIControlStateNormal];
self.growButton.layer.borderColor = [UIColor greenColor].CGColor;
self.growButton.layer.borderWidth = 3;
self.growButton.backgroundColor = [UIColor redColor];
[self.growButton addTarget:self action:@selector(onGrowButtonTaped:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.growButton];
[self.growButton mas_makeConstraints:^(MASConstraintMaker *make) {
//mas_equalTo()没有写参考对象的时候,是指父视图
make.top.left.right.mas_equalTo(0);
make.bottom.mas_equalTo(-350);
}];
}
- (void)onGrowButtonTaped:(UIButton *)sender{
self.isExpanded = !self.isExpanded;
if (!self.isExpanded) {
[self.growButton setTitle:@"点我展开" forState:UIControlStateNormal];
}else{
[self.growButton setTitle:@"点我收起" forState:UIControlStateNormal];
}
[self.view setNeedsUpdateConstraints];
[self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:0.3 animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)updateViewConstraints{
//这里使用update也能实现效果
//remake会将之前的全部移除,然后重新添加
__weak typeof(self) weakself = self;
[self.growButton mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.mas_equalTo(0);
//这里重写全部约束,之前的约束都将无效
if (weakself.isExpanded) {
make.bottom.mas_equalTo(0);
}else{
make.bottom.mas_equalTo(-350);
}
}];
[super updateViewConstraints];
}
实例五:
masonry :比例
#pragma mark - 比例
- (void)multipliedBy{
UIView *topView = [[UIView alloc]init];
[topView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:topView];
UIView *topInnerView = [[UIView alloc]init];
[topInnerView setBackgroundColor:[UIColor greenColor]];
[topView addSubview:topInnerView];
UIView *bottomView = [[UIView alloc]init];
[bottomView setBackgroundColor:[UIColor orangeColor]];
[self.view addSubview:bottomView];
UIView *bottomInnerView = [[UIView alloc]init];
[bottomInnerView setBackgroundColor:[UIColor blueColor]];
[bottomView addSubview:bottomInnerView];
[topView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.mas_equalTo(0);
make.height.mas_equalTo(bottomView);
}];
[topInnerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(0);
//宽是高的3倍
make.width.mas_equalTo(topInnerView.mas_height).multipliedBy(3);
make.center.mas_equalTo(topView);
}];
[bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.bottom.right.mas_equalTo(0);
make.height.mas_equalTo(topView);
make.top.mas_equalTo(topView.mas_bottom);
}];
[bottomInnerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.mas_equalTo(bottomView);
//高是宽的3倍
make.height.mas_equalTo(bottomInnerView.mas_width).multipliedBy(3);
make.center.mas_equalTo(bottomView);
}];
}
完整Demo
================2016 12 26 补充=================
1、约束方法的简写,避免出现错误
//比如第一个例子:
[_redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.view.mas_left).with.offset(20);
//可以改为:make.left.mas_equalTo(self.view.mas_left).offset(20)
//虽然只是少了一个with,但是会减少很多bug,因为经常会出现把with打为
//width,代码又没有报错误,但是运行了就崩溃,就很难找到问题所在了
make.bottom.mas_equalTo(self.view.mas_bottom).with.offset(-80);
make.height.equalTo(@50);
}];
2、Masonry关于UILabel的约束
宽度自适应:UILabel 的内容宽度是根据内容而定,并且是单行显示,可以设置uilabel 的抗压和抗拉属性
//1、宽度不够时
[_label1 setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
//2、宽度够时
[label setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
高度自适应:UILabel 的宽度是固定的,高度自适应,只要设置label 的行数就可以了
label.numberOfLines = 0;