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

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

方法一:
这里使用一个宽度可变的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];
*/

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

[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);
}];

实现效果


效果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容