内容字号:默认大号超大号

段落设置:段首缩进取消段首缩进

字体设置:切换到微软雅黑切换到宋体

OSX AutoLayout原理介绍

2018-11-07 18:05 出处:清屏网 人气: 评论(0

Auto Layout 是苹果公司在iOS6发布的界面布局技术,为了适配不同大小屏幕及屏幕变化而推出的一种技术方案,旨在实现一次编写布局界面UI,自动适应所有屏幕布局,并随着iOS SDK的迭代逐步完善了各种布局API、提供多种使用Auto Layout的布局方式。实际上Auto Layout算法本身并非有Apple发明,Auto Layout源于Cassary约束解析工具包。该算法由Alan Borning、Kim Marriott、Peter Stuckey、Yi Xiao于1997年发布,该算法的主要思想是:将基于约束系统的布局规则(本质上是表示视图布局关系的线性方程组)转化为表示规则的视图几何参数。

传统的布局

frame 布局

传统的布局方式是基于Frame来做UI控件的界面布局的,即设置控件在父视图中的起始坐标点Origin(x,y)和控件的大小Size(width,height),为了精确,我们必须计算每个视图的frame。但布局一旦发生变化,相关frame都需要重新计算。然后这些计算都需要不断的手动动态的去计算,导致一旦有变化,就会需要去维护和调试。

自动缩放(auto resizing)

自动缩放的出现在一定程度上减轻了我们的负担。自动缩放规定父视图的frame变化时,视图的frame如何应对。如此一来,简化了布局响应外部变化所需的工作。但是他仅能应对外部父布局的变化,自身大小的变化则无法进行处理。

AutoLayout剖析

布局变化原因

外在变化:窗口缩放,设备旋转,屏幕尺寸不同,分屏模式等。

内在变化:内容展示变化,国际化,字体变化等。

AutoLayout方程式

先来看一张官方的图,表示一个约束的表达式。

下面来具体介绍下其各个变量的意义。

  • Item1、Item2:一般是UIView,表示该约束关系对应的两个视图,当约束等式表示尺寸时,其中一个Item为nil。
  • Attribute1、Attribute2:NSLayoutAttribute类型,表示约束属性。当约束等式表示尺寸时,其中一个Attribute为NSLayoutAttributeNotAnAttribute,表示占位,无任何意义。具体看下图
  • Relationship:NSLayoutRelation类型,表示约束关系,可以是=、>=、<=。
  • Multiplier:CGFloat类型,表示倍数关系,一般用于尺寸(eg:Item1的宽度为Item2的两倍,则Multiplier为2.0)
  • Constant:CGFloat类型,表示常数。

注意

  • 只有同类型的约束才能互相做约束
  • 建议开发中一直使用leading、trailing。leading表示前边、trailing表示后边,在阅读习惯从左到右的语言中,leading相当于left、trailing相当于right。在从右到左的语言中,leading相当于right、trailing相当于left。

AutoLayout 本质

Auto Layout本质就是一个线性方程解析Engine。基于Auto Layout的布局,不在需要像frame时代一样,关注视图尺寸、位置的常数,转而关注视图之间关系,描述一个表示视图间布局关系的约束集合,由Engine解析出最终数值。

一个约束对象NSLayoutConstraint,本质上是表示两个视图之间(当表示尺寸时只表示视图本身)布局关系的一个线性方程,该方程可以是线性等式、也可以是线性不等式。

多个约束对象组成是一个约束集合,本质上是表示某个界面上多个视图之间布局关系的线性方程组。方程组中的多个线性方程,以数字标识的优先级进行排序(UILayoutPriority,本质上是浮点型float)。

Auto Layout Engine根据按照线性方程的优先级从高到底对线性方程组进行解析,求得方程组的解。

  • 当设置的约束欠缺,即存在约束歧义,线性方程组有多个解,而不是唯一解。这便是约束错误的一种:约束不充分,可能导致视图丢失,视图错位。
  • 当设置的约束过多,存在多个优先级相同的描述同一个关系的线性方程,并且约束产生的效果不同(例如 View1.left = View2.right + 10 ; View1.left = View2.right + 20,优先级都为1000),线程方程组无解。这是约束错误的另一种:约束不可满足,产生约束约束冲突,控制台会Log错误日志,同样可能造成布局错误。

约束优先级

默认创建出来的约束优先级为UILayoutPriorityRequired(1000),称为必需约束;其他优先级小于1000的约束称为可选约束。Auto Layout Engine进行约束解析时,尝试着按优先级从高到低满足约束集合中的每一个约束,如果无法满足某个可选约束,则跳过;当优先级不同的两个约束描述的是同一个布局关系,Auto Layout会跳过优先级较低的约束。

Intrinsic Content Size

对于文本/图片等一些视图控件,可以通过其内在content推算出控件的大小。不是所有的控件都有Intrinsic Content Size。按钮,文本label,文字输入TextField,TextView,ImageView都可以根据内在的content内容计算控件的大小。

基于控件的内容content,有2个特定的约束:content hugging 收缩约束 和 content compression 扩张约束,这2个约束简称为CHCR。

IntrinsicHeight代表内部内容的高,IntrinsicWidth代表内部内容的宽

//content compression的约束条件:
View.height >= IntrinsicHeight
View.width >= IntrinsicWidth
//content hugging的约束条件:
View.height <= IntrinsicHeight
View.width <= IntrinsicWidth

从这几组约束来看,如果需要完整的显示内容就需要content compression的优先级尽量高,而如果需要尽量显示的紧凑一些占用空间小一些可以将content hugging优先级尽量设置高一些。

更加简洁易懂点的描述如下:

  • Content Hugging Priority: 该优先级表示一个控件抗被拉伸的优先级。优先级越高,越不容易被拉伸
  • Content Compression Resistance Priority: 该优先级和上面那个优先级相对应,表示一个控件抗压缩的优先级。优先级越高,越不容易被压缩

Auto Layout布局机制

创建视图树、描述视图之间的约束、设置优先级、设置视图内容,Layout Engine计算出视图位置、尺寸,绘制出对应的图层。

Auto Layout布局过程涉及延迟机制,并非一有约束更新就马上进行布局重绘,当有约束更改时,系统的默认做法是延迟更新,目的是实现批量更改约束、绘制视图,避免频繁遍历视图层级,优化性能。当更新约束太慢影响到后序代码逻辑,也可强制马上更新。

  • App启动后开启RunLoop,循环检测图层树中是否存在约束变化;
  • 当发生Constrints Change(直接or间接设置、更新、移除约束),RunLoop检测到约束变化;
  • RunLoop发现约束变化后,就会进入Deferred Layout阶段,视图的位置、尺寸值会在这个过程计算,设置到对应视图上,并绘制出来;
  • 执行完一轮布局,RunLoop会继续检查视图树的约束更新情况,当再次发现约束更新,则执行新一轮布局……
分享给小伙伴们:
本文标签: OSXAutoLayout

相关文章

发表评论愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。

CopyRight © 2015-2016 QingPingShan.com , All Rights Reserved.

清屏网 版权所有 豫ICP备15026204号