前段时间千牛iOS版本也从iOS 6.0开始支持,所以可以正式引入Auto Layout来进行界面布局。
这里记录下在UILabel上应用Auto Layout进行布局的过程。

一、业务场景

  1. 用三个UILabel展示一件商品的基本信息:标题,价格,销量;
  2. 标题排在最上面,左右两边至少留出20的边距,可以换行;
  3. 价格排在标题下面,左边与标题对齐,顶部和标题留出10的边距;
  4. 销量排在价格右边,字体略小,底部和价格对齐,左边留出10的边距;

类似如下布局:

二、准备工作

首先,新建一个界面如下,添加三个UILabel和一个UIButton:

接着,从淘宝网上找几件宝贝作为商品数据:

- (void)prepareTestData {self.data = @[@{@"title": @"【1元预定魔镜S超值礼包】数量有限先到先得(单拍不发货不退款)",@"price": @"¥ 1.00",@"soldQuantity": @"月销量1133"},@{@"title": @"预售 lovo罗莱家纺出品床上用品全纯棉床单四件套件 多彩格拉斯哥 \虎妈猫爸 剧中同款 全棉斜纹 手感柔软 活泼跳跃",@"price": @"预售价 ¥299.00",@"soldQuantity": @"月销量694"},@{@"title": @"小狗扫地机器人家用智能扫地机清洁吸尘器薄静音全自动充电V-M611 \高效智能清洁 顺丰包邮",@"price": @"¥ 1299.00",@"soldQuantity": @"月销量123"},@{@"title": @"小狗吸尘器",@"price": @"¥ 299.00",@"soldQuantity": @"月销量233"}];
}

三个UILabel的作用是分别显示title、price和soldQuantity字段的,而UIButton是用来切换数据,从而观察三个UILabel在不同内容下的布局情况。
一开始的情况是:

三、约束描述

Auto Layout直译过来就是自动布局,是通过创建一些数学上的关系描述来计算出各个View的布局信息,从而能够创建出通用的界面布局来合理地响应变化。
数学上的关系描述形如priceLabel.top = titleLabel.bottom * 1 + 10,在Objective-C中以NSLayoutConstraint的形式存在:

/* Create constraints explicitly.  Constraints are of the form "view1.attr1 = view2.attr2 * multiplier + constant" If your equation does not have a second view and attribute, use nil and NSLayoutAttributeNotAnAttribute.*/
+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;

四、添加约束

我们先为titleLabel添加约束。
如果是用代码手动添加约束的话,第一步需要做的是:

self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;

从命名就可以理解,在使用Auto Layout进行布局时,我们就不要将AutoresizingMask转换为约束条件了,以免遇到一些不必要的冲突。

接着,我们按照业务场景来为titleLabel创建约束条件:

    NSLayoutConstraint *c1 = [NSLayoutConstraint constraintWithItem:self.titleLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:150];NSLayoutConstraint *c2 = [NSLayoutConstraint constraintWithItem:self.titleLabel attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:20];NSLayoutConstraint *c3 = [NSLayoutConstraint constraintWithItem:self.titleLabel attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1 constant:-20];

第一个约束c1是指定titleLabel的top,因为业务场景没有描述,所以这里先设置了个150,保证可见;
第二个约束c2是保证左边距留20;
第三个约束c3是保证右边距最少要留20;
同时,我们在xib文件中将其Lines设置为0,表示支持多行。

这里的约束条件是描述self.titleLabelself.view之间的关系,那么应该将这些约束条件添加到这二者共有的superView上,即self.view,从而使其具有足够的布局信息:

[self.view addConstraints:@[c1, c2, c3]];

五、约束冲突

接着,我们直接运行程序,会遇到如下问题:

Unable to simultaneously satisfy constraints.Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
("<NSIBPrototypingLayoutConstraint:0x7c281f80 'IB auto generated at build time for view with fixed frame' V:|-(165)-[UILabel:0x7c283780]   (Names: '|':UIView:0x7c283a30 )>","<NSLayoutConstraint:0x7c281230 V:|-(150)-[UILabel:0x7c283780]   (Names: '|':UIView:0x7c283a30 )>"
)Will attempt to recover by breaking constraint
<NSIBPrototypingLayoutConstraint:0x7c281f80 'IB auto generated at build time for view with fixed frame' V:|-(165)-[UILabel:0x7c283780]   (Names: '|':UIView:0x7c283a30 )>Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

日志输出很明显地指出不能同时满足多个约束条件,然后下面列出了具体的相互冲突的约束条件:

("<NSIBPrototypingLayoutConstraint:0x7c281f80 'IB auto generated at build time for view with fixed frame' V:|-(165)-[UILabel:0x7c283780]   (Names: '|':UIView:0x7c283a30 )>","<NSLayoutConstraint:0x7c281230 V:|-(150)-[UILabel:0x7c283780]   (Names: '|':UIView:0x7c283a30 )>"
)

参考Visual Format Language,可以看出上面的约束条件是垂直距离165,而下面的约束条件是垂直距离150,无法同时满足。

那么这个垂直距离165的约束是哪里来的呢?IB auto generated at build time for view with fixed frame——IB自动生成的。参考这个解决方案,我们先在IB中添加上足够的约束,并勾选上Remove at build time

六、多行文本

从上图可以看出,虽然在xib中制定了Lines为0,但实际布局中并没有换行,这是因为在Auto Layout中需要设置一个属性来制定最大宽度:

self.titleLabel.preferredMaxLayoutWidth = self.view.frame.size.width - 40;

这里是已知业务场景,左右两端都至少要留白20,所以直接减去40。而在一些场景中,如果无法实现得知preferredMaxLayoutWidth的值,那么就需要分成两步来做(参考Intrinsic Content Size of Multi-Line Text):

- (void)viewDidLayoutSubviews
{[super viewDidLayoutSubviews];myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;[self.view layoutIfNeeded];
}

这样一来,titleLabel就支持多行了。

七、剩余约束

接下来,就是为另外两个UILabel添加约束了。同样地,也会遇到IB自动生成的约束冲突。按同样的方案解决冲突后运行:

可以看到现在三个UILabel可以很灵活地适应不同的内容了。
这里有个问题就是IB自动生成的约束冲突很烦人,如果配套创建了xib文件,可以考虑尽量使用IB添加约束条件,并根据需要将约束条件作为outlet链接到ViewController中,以便后续调整。

为了不至于展示重复的添加约束代码,这里改为以VFL格式来对label进行约束(销量label距离价格label左边距为10,底部对齐):

    NSDictionary *dict = NSDictionaryOfVariableBindings(_priceLabel, _soldQuantityLabel);NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"[_priceLabel]-10-[_soldQuantityLabel]" options:NSLayoutFormatAlignAllBottom metrics:nil views:dict];[self.view addConstraints:constraints];

考虑到Auto Layout的代码很容易重复(比如距离superView的左边距多少之类的约束),可以考虑建立起可复用代码作为库。

Auto Layout和UILabel相关推荐

  1. IOS使用Auto Layout中的VFL适配

    做登录页面,之前做都是用frame做,今天想着用Auto Layout中的VFL来做.觉得做的效果还是可以的(自恋一下下). 首先看下效果图和标记图 自己在做的过程中也遇到了好多问题,不过也一个一个的 ...

  2. 有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局?

    本文是投稿文章,作者:iOS122 Apple 算是最重视应用开发体验的公司了.从Xib到StoryBoard,从Auto Layout到Size Class,每一次的更新,都会给iOS应用的开发带来 ...

  3. 深入理解Auto Layout 第一弹

    form:https://zhangbuhuai.com/auto-layout-part-1/ By 张不坏 2015-07-16 更新日期:2015-07-17 文章目录 1. 写在前面 2. i ...

  4. Advanced Auto Layout Toolbox

    原文地址:https://www.objc.io/issues/3-views/advanced-auto-layout-toolbox/ Auto Layout was introduced in ...

  5. 深入剖析Auto Layout,分析iOS各版本新增特性

    先前写到的一篇Masonry心得文章里已经提到了很多AutoLayout相关的知识,这篇我会更加详细的对其知识要点进行分析和整理. 来历 一般大家都会认为Auto Layout这个东西是苹果自己搞出来 ...

  6. Beginning Auto Layout Tutorial in iOS 7: Part 1

    本篇是学习iOS Auto Layout难得的好资料,值得一读!资料来自www.raywenderlich.com ------------------------------------------ ...

  7. 学会爱上iOS自动布局(Auto Layout)

    本文翻译自Yari Dareglia的LEARN TO LOVE AUTO LAYOUT文章 先生们,女士们,让我们以正确的心态开始本教程吧:自动布局就是简单! 我花了一段时间来掌握自动布局是如何工作 ...

  8. Advanced Auto Layout:Programmatically Creating Constraints

    Programmatically Creating Constraints以编程方式创建约束 Whenever possible, use Interface Builder to set your ...

  9. 【Auto Layout】Xcode6及以上版本,创建Auto Layout 约束时产生的一些变化【iOS开发教程】...

    [#Auto Layout#]Xcode6创建Auto Layout 约束时产生的一些变化     通过两个小Demo来展示下变化: Demo1需求: 为控制器的根视图(图中的"控制器Vie ...

最新文章

  1. Springboot 简单的定时器
  2. 【转】Unity中的单位长度与像素之间的关系
  3. 「十二省联考 2019」皮配——dp
  4. Random Forest随机森林概述
  5. 最短哈密尔顿圈matlab解法_复杂制造过程最优哈密尔顿圈算法的MATLAB仿真与分析.doc...
  6. (五)构建和训练深度伪造自动编码器
  7. debian 查看php版本,在debian 9中为php7.0-fpm启用状态查询
  8. UVa1368 - DNA Consensus String
  9. mysql4ge表联表查询_【MySQL】MariaDB10.2新特性--Flashback
  10. 修改windows默认远程管理端口
  11. 华为二层创建vlan_华为二层交换机基本配置命令有哪些
  12. nssa和stub_stub与nssa的区别
  13. 英尺英寸和厘米的换算_英尺米换算(英尺英寸与厘米换算器)
  14. Jquery定时弹广告
  15. ESP8266串口WIFI 无线控制模块
  16. 使用再生龙镜像备份还原linux,以及遇到的问题和解决方法
  17. 教你十步实现内网穿透
  18. H.265/HEVC学习笔记:量化
  19. MariaDB数据库的备份和还原
  20. NDK(一):NDK 的集成

热门文章

  1. uni-app 介绍,什么是uni-app,它是干嘛的
  2. 高可用服务设计之二:Rate limiting 限流与降级
  3. 【死链】JDK1.7中HashMap在多线程环境的并发问题源码分析
  4. 在windows下编译erlang内建函数(nif)的dll文件
  5. 如何在pdf文件中编辑页眉页脚
  6. CISCO 服务器配置 RAID 指南及安装操作系统
  7. 来看看怎么通过a标签打开一个对话框
  8. 我的世界bc端mysql_[BC端简介] BungeeCord跨服群组简介
  9. 虚拟机win7 DNS 不可用
  10. VINS-mono之IMU预积分(IMU预积分引出)