13、在IB中使用Auto Layout
在frame系统中,最重要的就是尺寸和位置,通过设置View的frame属性来表示它的位置和尺寸,从而确定布局。
Auto Layout是布局的另一种表示方法,这套布局系统中没有位置和尺寸,只有约束。添加的约束最终会被系统转化为frame。
1 最好不要在Auto Layout中设置frame
在Auto Layout中设置frame可能会导致设置无效。
AutoLayout系统有别于frame系统,当一个控件使用了Auto Layout,设置了必要的约束,此时在viewDidLoad中设置frame是无效的,只有把设置frame的代码放到viewDidLayoutSubviews方法才会生效,而且最好放在viewDidLayoutSubviews方法里面,先调用super.viewDidLayoutSubviews(),否则可能会出现某些未知的错误。
当一个View使用了Auto Layout布局,系统在layout subviews时会加载它的约束信息,通过约束信息布局这个View。其实通过viewDidLoad方法设置frame起了作用,但是由于layout subviews是在它的后面执行的,所以在viewDidLoad里面设置frame是无效的。但是可以在viewDidLayoutSubviews方法里面进行设置,因为此时layout subviews已经完成。
2 约束
2.1 Auto Layout的数学公式
item1.attribute1 = multiplier * item2.attribute2 + constant
在这个公式中,item1、item2是要布局的View;attribute1、attribute2是约束属性;"="是约束中的关系;multiplier和constant是调节这种关系的因子,是这种线性关系的常量。在通常情况下,multiplier是1.0。
创建一个约束实例
@available(iOS 6.0, *)
public convenience init(item view1: Any, attribute attr1: NSLayoutConstraint.Attribute, relatedBy relation: NSLayoutConstraint.Relation, toItem view2: Any?, attribute attr2: NSLayoutConstraint.Attribute, multiplier: CGFloat, constant c: CGFloat)
设置一个约束:
let left = NSLayoutConstraint(item: aSubView, attribute: .left, relatedBy: .equal, toItem: aSuperView, attribute: .left, multiplier: 1.0, constant: 100)
AutoLayout是靠约束来描述两个View之间的关系的,这个View必须是兄弟关系或者是父子关系。
2.2 约束属性
public enum Attribute : Int {
case left = 1
case right = 2
case top = 3
case bottom = 4
case leading = 5
case trailing = 6
case width = 7
case height = 8
case centerX = 9
case centerY = 10
case lastBaseline = 11
@available(iOS 8.0, *)
case firstBaseline = 12
@available(iOS 8.0, *)
case leftMargin = 13
@available(iOS 8.0, *)
case rightMargin = 14
@available(iOS 8.0, *)
case topMargin = 15
@available(iOS 8.0, *)
case bottomMargin = 16
@available(iOS 8.0, *)
case leadingMargin = 17
@available(iOS 8.0, *)
case trailingMargin = 18
@available(iOS 8.0, *)
case centerXWithinMargins = 19
@available(iOS 8.0, *)
case centerYWithinMargins = 20
case notAnAttribute = 0
}
约束属性是数学公式中的attribute1和attribute2,也是NSLayoutConstraint初始化方法中的attribute参数。
-
left与leading是相同的,right与trailing是相同的,leftMargin与leading Margins是相同的,rightMargin与right Margins是相同的。
-
带Margin的属性是以Margin为参照系建立关系的,不带Margin的属性是以View本身为参照系建立关系的。通常来说,View都有自己的Margin,也就是边缘的留白,带Margin的属性在计算关系时计算的是Margin的边缘,不带Margin的属性在计算关系时计算的是View的边缘。
-
带Baseline的属性是指以View里面的内容基准线为参照系建立关系的,因为通常来说View的边缘并不是它内容的边缘,带Baseline的case是以View内容的边缘来计算关系的,不带Baseline的case是以View的边缘来计算关系的。
2.3 约束关系
public enum Relation : Int {
case lessThanOrEqual = -1
case equal = 0
case greaterThanOrEqual = 1
}
2.4 multiplier和constant
通常设置multiplier为1.0,一般只有在布局等分排列的时候才将multiplier设置为其他值,根据不同情况设置对应的constant的值,constant是调节布局关系时设置的最重要的值。
2.5 约束的创建和添加
创建:
let left = NSLayoutConstraint(item: aSubView, attribute: .left, relatedBy: .equal, toItem: aSuperView, attribute: .left, multiplier: 1.0, constant: 100)
addConstraint是指添加一个约束,addConstraints是指添加一个数组
2.6 约束的优先级
当设置的约束过多时就会可能引起约束之间的相互冲突。系统会随机选择其中一些约束来确定布局。
优先级对应的就是NSLayoutConstraint累中的priority属性,该属性的类型是UILayoutPriority,而UILayoutPriority是Float类型。
public typealias UILayoutPriority = Float
但是在实际应用中,priority设置的范围是1-1000,在IB中只能设置1-1000中的整数。
下面是几个常用的优先级:
public let UILayoutPriorityRequired: UILayoutPriority //1000
public let UILayoutPrioritDefaultHigh: UILayoutPriority //750
public let UILayoutPrioritDefaultLow: UILayoutPriority //250
public let UILayoutPrioritFittingSizeLevel: UILayoutPriority //250
UILayoutPriorityRequired是最高优先级,UILayoutPrioritDefaultHigh是压缩阻力的优先级,UILayoutPrioritDefaultLow是内容吸附的优先级,UILayoutPrioritFittingSizeLevel是内置的最低优先级
如果在6个约束中挑选4个约束,系统会挑选优先级最高的4个。如果优先级都相同,则会随机挑选4个。我们可以通过设置优先级来达到布局复杂UI的目的。
3 Auto Layout相关的菜单介绍
3.1 Update frames介绍
在IB中同时存在frame和Auto Layout两种布局体系。当添加约束确定与frame确定的布局冲突时,点击Update frames按钮可以自动改变frame,使其与Auto Layout确定的布局保持一致。
3.2 Embed in Stack介绍
3.3 Align介绍
3.4 Add New Constraints介绍
3.5 Resolve Auto Layout Issue介绍
4 Show the size inspector再介绍
4.1 Intrinsic Size --固有尺寸
所谓固有尺寸就是不需要设置width和height,系统可以通过它的内容属性自动获取大小。
无需设置尺寸的约束的视图有:
- Label
- Button
- SegmentControl
- TextField
- Slider(无需确定高度,但是必须确定宽度)
- Switch
- ActivityIndicatorView
- ProgressView(无需确定高度,但是需要确定宽度)
- PageControl
- Stepper
- ImageView(当ImageView的实例显示图片且ImageView的size与图片的大小相同时)
- DatePicker(无需确定高度,但是需要确定宽度)
- PickerView(无需确定高度,但是需要确定宽度)
4.2 Content Compression Resistance – 压缩阻力
压缩阻力是指一个视图保护其内容完整性的能力,压缩阻力越大,该视图保护其内容完整性的能力越强,内容越不容被压缩或者裁剪。
4.3 Content Hugging – 内容吸附
内容吸附是指一个视图保持它的尺寸与其内容尺寸相匹配的能力,内容吸附能力越强,该视图保持她的尺寸和内容尺寸相一致的能力越强;