Auto Layout的生命周期
Layout Engine 界面布局过程App启动后,主线程的Run Loop会一直处于监听状态
每个视图在得到自己的布局之前,Layout Engine 会将视图、约束、优先级、固定大小通过计算转换成最终的大小和位置
当约束发生变化后,Layout Engine 在碰到约束变化后会重新计算布局,获取到布局后调用 superview.setNeedLayout()
会触发Deffered Layout Pass(延迟布局传递),在里面做容错处理(约束丢失等情况)并把view标识为dirty状态
然后Run Loop再次进入监听阶段。
当下一次刷新屏幕动作来临(或者是调用layoutIfNeeded)时,Layout Engine 会从上到下调用 layoutSubviews()
通过 Cassowary算法计算各个子视图的位置,算出来后将子视图的frame从Layout Engine拷贝出来,接下来的过程就跟手写frame是一样的了。
Auto Layout 性能问题
iOS 12 使得 Auto Layout 具有了和手写布局几乎相同的高性能
使用 Auto Layout 一定要注意多使用 Compression Resistance Priority 和 Hugging Priority,利用优先级的设置,让布局更加灵活,代码更少,更易于维护。
'https://github.com/ming1016/study/wiki/Masonry'
AutoLayout的一些基本概念
利用约束来控制视图的大小和位置,系统会在运行时通过设置的约束计算得到frame再绘制屏幕
两个属性Content Compression Resistance(排挤,值越高越固定)和Content Hugging(拥抱),Masonry代码如下
//content hugging 为1000
[view setContentHuggingPriority:UILayoutPriorityRequired
forAxis:UILayoutConstraintAxisHorizontal];
//content compression 为250
[view setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
forAxis:UILayoutConstraintAxisHorizontal];
multipler属性表示约束值为约束对象的百分比,在Masonry里有对应的multipliedBy函数
//宽度为superView宽度的20%
make.width.equalTo(superView.mas_width).multipliedBy(0.2);
AutoLayout下UILabel设置多行计算需要设置preferredMaxLayoutWidth
label.preferredMaxWidth = [UIScreen mainScreen].bounds.size.width - margin - padding;
preferredMaxLayoutWidth用来制定最大的宽,一般用在多行的UILabel中
systemLayoutSizeFittingSize方法能够获得view的高度
iOS7有两个很有用的属性,topLayoutGuide和bottomLayoutGuide,这个两个主要是方便获取UINavigationController和UITabBarController的头部视图区域和底部视图区域。
//Masonry直接支持这个属性
make.top.equalTo(self.mas_topLayoutGuide);
AutoLayout关于更新的几个方法的区别
setNeedsLayout:告知页面需要更新,但是不会立刻开始更新。执行后会立刻调用layoutSubviews。
layoutIfNeeded:告知页面布局立刻更新。所以一般都会和setNeedsLayout一起使用。如果希望立刻生成新的frame需要调用此方法,利用这点一般布局动画可以在更新布局后直接使用这个方法让动画生效。
layoutSubviews:系统重写布局
setNeedsUpdateConstraints:告知需要更新约束,但是不会立刻开始
updateConstraintsIfNeeded:告知立刻更新约束
updateConstraints:系统更新约束
Masonry使用注意事项
用mas_makeConstraints的那个view需要在addSubview之后才能用这个方法
mas_equalTo适用数值元素,equalTo适合多属性的比如make.left.and.right.equalTo(self.view)
方法and和with只是为了可读性,返回自身,比如make.left.and.right.equalTo(self.view)和make.left.right.equalTo(self.view)是一样的。
因为iOS中原点在左上角所以注意使用offset时注意right和bottom用负数
网友评论