iOS实战之从左往右自动填充布局页面

版权声明:书写博客,不为传道受业,只为更好的梳理更好的记忆,欢迎转载与分享,更多博客请访问:http://blog.csdn.net/myinclude 和 http://www.jianshu.com/u/b20be2dcb0c3 https://blog.csdn.net/myinclude/article/details/79841036

这里主要讲的就是控件宽度可变时的计算:

方法一:
这里使用一个宽度可变的Button,宽度不变的两个Label从左往右依次排布来测试。这里使用三组组合,每一组都用一个UIView包裹。

首先为了测试,Button的标题,依次为:

NSArray *btnTitle = @[@"我是一个长标题,很长很长很长很长的标题",@"我是短标题",@"标题"];

titleLB的文本:

titleLB.text = @"我是固定的标题";

flagLB的文本:

flagLB.text = @"立个flag";

接下来就是计算:
首先flagLB和titleLB的Size我们可以确定,可以给一个固定的值,也可以自动计算,由于button的title是可变的,所以我们采用自动计算

这里计算,我们需要使用一个系统方法:

CGSize constrainedSize = CGSizeMake(0, MAXFLOAT);
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
CGRect textRect = [title boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin 
  attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15]} context:nil];

这样就能计算一个文本的size,类似于iOS7以前使用的sizeWithFont,从这个Size可以获取文本的宽高。

由于这三者的Size都确定了,布局写起来也就简单了:

CGSize constrainedSize = CGSizeMake(0, MAXFLOAT);
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
CGRect textRect = [title boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15]} context:nil];

CGRect textRect2 = [titleLB.text boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:titleLB.font} context:nil];

[button mas_remakeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(bgView.mas_left).offset(5);
    make.centerY.equalTo(bgView);
    make.height.mas_equalTo(20);
    make.width.mas_equalTo(MIN(textRect.size.width+10 , screenWidth-75-textRect2.size.width));
}];

[titleLB mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(button.mas_right).offset(5);
    make.height.mas_equalTo(18);
    make.width.mas_equalTo(textRect2.size.width);
    make.centerY.mas_equalTo(bgView);
}];

[flagLB mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(titleLB.mas_right).offset(5);
    make.size.mas_equalTo(CGSizeMake(60, 13));
    make.centerY.mas_equalTo(bgView);
}];

最关键的就是这句:
make.width.mas_equalTo(MIN(textRect.size.width+10 , screenWidth-75-textRect2.size.width));
可能有人会有疑问,这里不是能获得button的titleSize吗,直接设置titleSize.width不就可以了吗,如果这里title非常长的话,那么后面那两个label就会顶出到屏幕外面,这个是不符合设计的,所以需要对button的宽度进行限制。这里是对width进行判定,将titleSize和剩余屏幕宽度进行比较,如果button长度小于屏幕剩余宽度,则宽度为button的title宽度,如果button标题长度过长,则button的宽度为剩余屏幕宽度。
最后上传一个效果:

效果图


方法二:
理论
- 约束优先级: 在Autolayout中每个约束都有一个优先级, 优先级的范围是1 ~ 1000。创建一个约束,默认的优先级是最高的1000。
- Content Hugging Priority: 该优先级表示一个控件抗被拉伸的优先级。优先级越高,越不容易被拉伸,默认是250。
- Content Compression Resistance Priority: 该优先级和上面那个优先级相对应,表示一个控件抗压缩的优先级。优先级越高,越不容易被压缩,默认是750


所以默认情况下两边的label的Content Hugging和Content Compression优先级都是一样的,为了让右边的label完全显示,那么我们需要增大右边label的抗压缩级,或者减小左边label的抗压缩级,总之是得让右边的抗压缩级大于左边的label,这样才能让右边的label内容优先显示。

UIView中关于Content Hugging 和 Content Compression Resistance的方法有:

- (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);

- (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
- (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);

代码:

    [self.leftLB mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@(30));
        make.left.equalTo(self.view).offset(10);
        make.centerY.equalTo(self.view).offset(-50);
        make.right.mas_lessThanOrEqualTo(self.rightLB.mas_left);
    }];

    [self.rightLB mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@(30));
        make.left.mas_greaterThanOrEqualTo(self.leftLB.mas_right);
        make.right.equalTo(self.view).offset(-10);
        make.centerY.equalTo(self.leftLB);
    }];

    [self.leftLB1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@(30));
        make.left.equalTo(self.view).offset(10);
        make.centerY.equalTo(self.view).offset(50);
        make.right.mas_lessThanOrEqualTo(self.rightLB1.mas_left);
    }];

    [self.rightLB1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@(30));
        make.left.mas_greaterThanOrEqualTo(self.leftLB1.mas_right);
        make.right.equalTo(self.view).offset(-10);
        make.centerY.equalTo(self.leftLB1);
    }];

    //让左边的label抗压缩性降低,即可压缩,越高越不容易被压缩
    [self.leftLB1 setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
    /*
    或者让左边的label抗拉伸性增高,越高越不容易被拉伸
    [self.leftLB1 setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    或者让右边的label抗压缩性增高,即可扩张
    [self.rightLB1 setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    或者让右边的label抗拉伸性降低,即可扩张
    [self.rightLB1 setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
    */

最关键的注释那几句话,随便选中一句都可以达到效果。

效果图


最后:

附加一个很好用的相似布局自动排列:

[self.container addSubview:self.label1];
[self.container addSubview:self.label2];
[self.container addSubview:self.label3];
//将控件添加到一个数组里面
NSArray *array = @[self.label1,self.label2,self.label3]; 
/*
使用方法,一次性配置:横向布局,控件间距90,第一个控件与父容器间距15,
最后一个控件与父容器间距15
*/
[array mas_distributeViewsAlongAxis:MASAxisTypeHorizontal 
withFixedSpacing:90 leadSpacing:15 tailSpacing:15];  

//设置单个view的大小,在父view的与需要平分的方向的垂直方向的位置,例如需要在水平方向平分,就给一个竖直方向的位置
[array mas_makeConstraints:^(MASConstraintMaker *make) {
  make.top.equalTo(@120);
  make.height.equalTo(@75);
}];

实现效果
效果

猜你喜欢

转载自blog.csdn.net/myinclude/article/details/79841036