窥探iOS可视化编程中AutoLayout的精髓

在iOS开发中,使用可视化编程能够简单快速的拖拽出令人满意的UI。但是,除了简单的拖拽之外,还有一项工作对于可视化编程来讲必不可少,那就是AutoLayout自适应布局。因为,没有进行AutoLayout的UI将无法适应屏幕大小不同的机型。本文主要基于Xcode 7.2.1总结一下个人在可视化编程中进行AutoLayout的几点经验,大神请绕过。


一、关于约束

在可视化编程中进行AutoLayout的方法就是添加约束。通过添加合适的约束,使控件能够按照预期的位置和大小显示在屏幕大小不同的机型上,也就实现了AutoLayout自适应布局。

1、添加约束

学习过可视化编程的小猿们应该都知道添加约束的几种主要方法:

方法一:使用 Interface Builder 界面右下角的 Stack 、Align 、Pin 、Resolve Auto Layout Issues 四个约束操作按钮。

方法二:在 Interface Builder 界面上,按住 control 键,从控件开始拖动鼠标到参考控件上,松开鼠标就会弹出约束选择窗口(如图 1-1)。

图 1-1

方法三:在 Interface Builder 界面左侧的 Document Outline 窗口中,按住 control 键,从控件开始拖动鼠标到参考控件上,松开鼠标就会弹出约束选择窗口(如图 1-2)。

图 1-2

2、约束分类

从上面的截图中我们可以发现,约束大致上可以分为三类:

2.1  距离约束

距离约束主要用于限定控件相对于参考控件的距离关系。相对于不同的参考控件,距离约束的具体名称会有一些区别,但作用效果基本相同。例如:

相对于根 View 的距离约束为:Leading Space to Container Margin 、Trailing Space to Container Margin 、Vertical Spacing to Top Layout Guide 、Vertical Spacing to Bottom Layout Guide 。

相对于非根 View 的父 View 的距离约束为:Top Space to Container 、Leading Space to Container 、Bottom Space to Container 、Trailing Space to Container 。

相对于无包含关系的其它控件的距离约束为:Horizontal Spacing 、Vertical Spacing 。

2.2  对齐约束

对齐约束主要用于限定控件相对于参考控件的距离关系。同样,相对于不同的参考控件,对齐约束的具体名称也会有一些区别。例如:

相对于跟 View 或父 View 的对齐约束为:Center Horizontally in Container 、Center Vertically in Container 。

相对于无包含关系的其它控件的对齐约束为:Center Horizontally 、Center Vertically 。

2.3  宽高约束

宽高约束主要用于限定控件相对于参考控件的宽高关系,包括:Equal Widths 、Equal Heights 、Aspect Ratio 。

二、窥探精髓

上面讲述了关于约束的基本内容,但具有可视化编程经验的小猿们都清楚,只知道这些基本内容还远不足以添加出能够满足各种 AutoLayout 需求的约束。所以说,接下来我们就深入其中,窥探精髓。

在 Interface Builder 界面中选中某个控件,我们就可以在 右侧 Utilities 窗口 —> Size 选项卡 —> Constraints 选项 下查看已经添加的约束(如图 2-1),并可以点击 Edit 或者双击进入约束详情对这些约束进行编辑。

图 2-1

或者我们可以直接在 Interface Builder 界面选中控件上的具体约束,在 右侧 Utilities 窗口 —> Size 选项卡 下就会显示约束详情(如图 2-2),可直接进行编辑。

图 2-2

约束详情中都包括哪些内容呢?下面我们就来详细了解一下。

在图 2-2 中我们可以看到,约束详情的最上面是约束的名称,也就是图中的 Center X Alignment Constraint ;最下面是一个 Placeholder 选项,内容是 Remove at build time ,从字面意思就可以知道,如果选择了这个选项,编译时将会移除这个约束,所以说一般情况下我们是不会勾选这个选项的;详情中剩余的内容也就是需要重点讲述的内容,其实这些内容都可以用 NSLayoutConstraint 的属性进行描述:

First Item:(id firstItem 属性).(NSLayoutAttribute firstAttribute 属性),其中的 firstAttribute 属性是可选的。

Relation:NSLayoutRelation relation 属性,有三个选项可供选择:Less Than or Equal(<=)、Equal(=)以及 Greater Than or Equal(>=),默认是 Equal(=)。

Second Item:(id secondItem 属性).(NSLayoutAttribute secondAttribute 属性),其中的 secondAttribute 属性是可选的。

Constant:CGFloat constant 属性,常数,可以手动输入,用以对约束进行调整。

Priority:UILayoutPriority priority 属性,优先级,默认值为1000,可以手动输入,一般不做修改。

Multiplier:CGFloat multiplier 属性,系数,可以手动输入,用以对约束进行调整。

Identifier:NSString *identifier 属性,约束标识。

这些内容遵循一个公式来限定约束:

First Item =(<=、>=) Multiplier × Second Item + Constant

这个公式就是约束的精髓,也就是可视化编程 AutoLayout 的精髓。公式中 First Item 的 firstAttribute 属性和 Second Item 的 secondAttribute 属性是可选的,Multiplier 系数和 Constant 常数可以手动输入,所以说我们可以通过编辑约束来随心所欲的修改约束,进而限定控件的位置和大小,实现可视化编程中的各种 AutoLayout 需求。

三、特殊需求

1、Label 的高度自适应

Label 的高度自适应非常简单。具有可视化编程经验的小猿们都知道,给 Label 加约束时不添加宽高约束也不会报错,因为系统默认 Label 的 numberOfLines = 1,height = 20.5,宽度根据文字长短自适应。但有些时候,我们需要使用 Label 显示一段很长的文本,就需要进行高度自适应:添加约束限定 Label 宽度,在 右侧 Utilities 窗口 —> Attributes 选项卡 —> Label 选项 下将 Lines 设置为0。

2、ScrollView 的 AutoLayout

曾经尝试过在可视化编程中对 ScrollView 进行 AutoLayout 的小猿们都知道,如果我们以 ScrollView 作为参考控件给其上的控件添加宽高约束,系统就会报错。怎么办呢?曾经有朋友告诉过我一个使用三方解决的方法,具体是什么三方我不记得了,因为我基本不会用这种方法。

那么我是怎么解决的呢?其实只要清楚问题的根源,我们就可以很简单的解决它。

我们使用代码创建 ScrollView 的时候,都必须要给定它的 contentSize 属性,但是我们在可视化编程时并没有对这一属性进行设置。所以,当我们以 ScrollView 作为参考控件给其上的控件添加宽高约束时,系统自然就会报错。解决问题办法也就是在给 ScrollView 上的控件添加宽高约束时以除 ScrollView 以外的其它控件作为参考控件。

考虑到我们可能会在 ScrollView 上添加很多个控件,最好的作法就是先在 ScrollView 上添加一个空白 View 作为 contentView ,添加好约束后将需要添加的控件添加到 contentView 上,这时就可以按照正常添加约束的方法给这些控件添加约束了。下面的动画演示的是在 ScrollView 上添加一个与根 View 等宽、高度为根 View 高度2倍的 contentView ,并添加约束的过程:

图 3-1

3、TableViewCell 的高度自适应

在实际开发中可能经常会遇到 Cell 的高度要根据显示的文字的多少进行调整的需求,这种情况下,如果我们通过可视化编程来定制 customCell ,又该怎样添加约束来使 customCell 的高度能够自适应呢?

首先,我们要给 customCell 中显示文字的 Label 添加约束:

第一步:限定 Label 的宽度,但不要限定 Label 的高度,因为 Label 高度自适应之后 customCell 才能高度自适应;

第二步:通过 Leading Space 或 Trailing Space 或 Center.X 限定 Label 在水平方向上的位置;

第三步:限定 Label 的 Top Space 和 Bottom Space 两个距离约束;

第四步:在 右侧 Utilities 窗口 —> Attributes 选项卡 —> Label 选项 下将 Lines 设置为0。

然后,我们要在代码中设置 TableView 的 estimatedRowHeight 和 rowHeight 属性:

self.tableView.estimatedRowHeight = 30 ;    // 设置 customCell 的估计高度

self.tableView.rowHeight = UITableViewAutomaticDimension;    // 设置 customCell 自适应高度

这样,我们就实现了 TableViewCell 的高度自适应。

四、实例演示

接下来根据实际开发中的一个 AutoLayout 需求,来给大家做一个小小的演示。之前一个朋友给提了一个 AutoLayout 的需求,具体的 UI 效果如图 4-1,要求三个 ImageView 等宽等高,之间的两个间隔和屏幕边缘的两个间隔宽度相等。朋友告诉我说他是在四个间隔区域使用了四个空白的占位 View ,然后再添加如下约束:

1、添加距离约束:限定两边的空白 View 与屏幕边缘的距离为0,限定四个占位 View 与三个 ImageView 两两之间的距离为0;

2、添加对齐约束:限定四个占位 View 和三个 ImageView 相对于根 View 竖直居中;

3、添加宽高约束:限定四个占位 View 和三个 ImageView 的高度均为 0.2 × 屏幕高度,限定四个占位 View 的宽度均为 0.07 × 屏幕宽度,限定三个 ImageView 的宽度均为 0.24 × 屏幕宽度。

图 4-1

如果试着把这些约束添加一遍,就会发现这种方法非常麻烦,还容易出错。但是,这篇文章读到这里,我们已经完全没必要再使用这种浪费空白占位 View 又非常麻烦的方法了。我们完全可以只对三个 ImageView 添加约束来实现图 4-1中的 UI 效果。计算 Multiplier 系数的过程请自行脑补,下面只演示添加约束的过程:

图 4-2

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

推荐阅读更多精彩内容