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

2017-04-25  本文已影响179人  SuAdrenine

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

方法一:
这里使用一个宽度可变的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的宽度为剩余屏幕宽度。
最后上传一个效果:

效果图

方法二:
理论


所以默认情况下两边的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];
*/

更新:让一个控件既不被压缩也不被拉伸

[label setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[label setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh 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);
}];

实现效果


效果
上一篇 下一篇

猜你喜欢

热点阅读