Autolayout 你理解的够深刻吗(1)

Autolayout 中 比如你在某一个视图里预留了一个视图后期是通过代码创建的视图需要addSubview上去 则记得先修改原视图的高度约束的constant,然后再获取这个原始图的bounds就能马上拿到正确的尺寸了或者添加新的视图,不然就会因为之前默认的xib里的预留视图高为0而导致后面addsubview报错。当然自动布局最大的地方就是约束一定要清晰不冲突,不然就算是各种 setNeedsLayout SetNeedsUpdateConstraints layoutSubviwes layoutIfNeeded 都不起作用 当然你也可以尝试看看对添加的视图进行调用上面的方法,但一般来说只要约束正确了,且操作前就设置了constant,那就是正确的了。如果遇到几个不确定的视图排列一定要顾好各个约束的优先级或阻止压缩或阻止扩张优先级,如果intraSize自动算高的之间都不确定又要排列在一起那也可以通过设置这两个对象的高为0然后优先级为high而不是required,这样防止在并未设置预留视图的constant前就操作该视图时导致的编辑器autolayout报错。

另外在比如在cellForRow里通过对cell设置model来判断model逻辑实时Masonry添加移除新的视图时,该cell其实还没有被return出去所以此时的cell中操作的xib控件都是获取的预先的xib里的值,而不是具体的设备真实的,这时只能不依赖于当前xib本身的大小进行其他操作了。比如计算label的高度等,而要改用设备uiscreen上来具体测算。

以constraint为基础的autolayout设计允许根据外部和内部大小的改变自动适配尺寸的图形界面,
外部改变包括:
1 用户改变window大小(MacOS)
2 用户进入或离开SplitView分屏(iPad-iOS)
3 设备旋转,想要支持Size-Classes,和不同屏幕尺寸,录音和电话出现或消失时。
这些变化都可以在RunTime中出现因此需要应用支持动态响应这种尺寸的变化,Autolayout正好OK
内部改变包括:
1 显示的内容改变
2 支持国际化时(不同语言文字占用空间不同,同语言但各个地区的格式不同可能带来的变化,不同语言排版不同比如阿拉伯和希伯来语是从右到左排列)
3 APP支持DynamicType动态调整(如动态改变字体等)

1. 纯编码样式的设置frame和position
2. autoresizing mask定义了该如何改变尺寸当父视图发生变化时,简化如何适配外部改变带来的变化。简单的OK,复杂的则需要配合手动编码。
3. 考虑视图尺寸不如考虑视图关系的Autolayout使用的是constraint约束。关注基于constraint的size和location。
4. 如果控件是有intrinsic content size则会自动计算好当前内容适合的大小无需大小的约束,如果不是则给定了一个默认大小然后通过添加约束保持这个大小。
5. Text Items有一个baseline的属性,
6. Autolayout的目标就是为视图之间的关系创造一个且唯一一个等式。但同时Autolayout也是支持创造不等式(大于 小于)。
7. 根据优先级创建可选约束,1000是必选的,其它都是可选的。所以若要动态改变优先级的约束则不能把要改变的设置为1000.约束会优先从高到低级别满足。
8. 【CHCR属性】 UIView and NSView没有intrinsic size。Sliders在iOS中有自动的width,在MacOS中根据不同的slider类型有intrinsic高宽。Labels, buttons, switches, and text fields都有intrinsic高宽。Text views 和 imageView高宽可变。intrinsicSize都是基于内容的, label or button基于文字多少和字体大小。其它则复杂点,如图像为空时则没有intrinsicSize有则为图像本身的大小。TextView当可滑动时没有intrinsicSize,如果不可滑动则根据是否有宽度来计算其intrinsicSize。Autolayout使用各个维度方向上的约束来阐述intrinsicSize,这个维度的约束就是contentHugging用来把内容包围的刚刚好,和compressionResistance用来把视图推向外部以防内容被剪切。 所以如果未来要设置的内容比现在计算出来的intrinsicSize要长则要设置其compression的属性要高了。当然如果你不通过intrinsicSize来确定拥有intrinsicSize的控件足够的尺寸约束就不再用设置这两个属性了。默认250的抗拉伸和750的抗压缩使其在内容变化时很容易自动扩展拉伸了,只要有可能在Autolayout中优先使用intrinsicSize比较好。如果要拉伸一系列的视图来填充空白,如果不设置hugging内容不超出当前的intrinsicSize还好,超出了又要填充。那谁来填充则要设置hugging。若hugging属性(即都保持刚刚好不被强制拉伸)都一样则Autolayout不知拉伸谁,系统已经默认伴我们把label的hugging设置为了比普通的默认值250高的251所以不担心label会被拉伸,因为它更能抗拉伸,而他后面的field默认是250则会根据距父视图training默默拉伸。但如果前面的label或者后面的field文字超长时,因为label是要优先保全自己就会尽量变大到刚刚好显示全自己就好,不会做多余的拉伸。所以field不断缩小,但field也有文字也有intrinsicSize,如果label要大到连field的intrinsicSize都不能忍了时,这时就要设置抗压缩compressionResistance了减小它则会再次缩小field。所以要达到完美就要既设置抗拉伸(比如基于当前内容的intrinsic,保持hugging高的优先显示,压缩或拉伸hugging低的。但优先级高的控件修改内容后根据intrinsic自动适配后,一旦超过后面控件的intrinsic了就尴尬了,因为后面压缩不能压缩到比自己的intrinsicSize还小。)又要设置抗拉伸(这时,设置好后面控件的抗压缩优先级底就能压缩了)。
9. Baseline constraints 只作用于view的intrinsic content height.如果这个view垂直方向上被拉伸或压缩则这个baseline constraints就不在正确的对齐了。
10. 如果一个view是根据intrinsic来定的,最好用999来定义优先级而不是required。这样既避免拉伸或压缩其尺寸的同时也同样防止特殊情况下的错误,因为尺寸错了也要好过出现错误。
11. Autolayout一共提供三种方式设置约束:views之间control+拖,pin+align工具,xib帮你设置在自己修改。(当你拖控件到画布上时,xib自动创建了距离左上角的原版默认隐形约束,这样直接运行就可以方便调试,但不要发布这样的隐形原型约束app就好了。当你设置了你第一个约束,系统会自动移除与你约束相关的那个视图上的所有原型约束,这样之后因为没有足够的约束导致布局就报错了。 drag-拖拽方式可以自动识别方向来决定给你的选项是水平还是垂直间距且按住了control控件拖拽也不怕拖歪因为不会强硬改变控件的位置。IB是根据当前控件的frame来创建约束的,所以拖拽都要大致确定一个位置。另外IB也可以自动帮我们的视图加约束Resolve Auto Layout Issues tool > Reset to Suggested Constraints.但一般还是满足不了我们的需求。)
12. intrinsicSize 使用系统默认 如果修改成了placeholder则只在设计时有build后就没有了
13. The top and bottom layout guides表示对当前VC上下可见区域的边际,如果不想视图内容穿过透明的bar延展,则各个控件单独设置。
14. margins默认指定了视图和子视图的间隔,默认是8.
15. 苹果建议:最好创建和它最邻近的视图的约束,避免直接设置view的宽高用最小或最大替代宽高,控件最好都有名字以方便定位,优先使用前后而不是左右,代码创建view时记得先设置translatesAutoresizingMaskIntoConstraints = NO,不然系统自动生成的约束可能与自己的约束相冲突. OSX和iOS中的Autolayout计算不一样,OSX可以修改窗口的内容和窗口大小,iOS只能修改当前场景的内容。
16. 模糊的Autolayout造成的原因:缺少必要的约束来唯一限定位置和大小,可选约束优先级是一样系统不知优先使用哪个。
17. 模糊的约束无法设置断点调试也没输出,很难在运行时发现,所以只用在调试中有方法可以检测,对可能有问题的view在调试窗口 调用hasAmbiguousLayout,会返回布尔值。或者 _autolayoutTrace 来输出诊断信息。
18. baseline alignment works only when the view is displayed at its intrinsic content height. If you stretch or shrink the view vertically, the text mysteriously appears in the wrong location.
19. If a control should always match its intrinsic content size, give it a very high content-hugging and compression-resistance priority (for example, 999).

AutoLayout官方参考

UIStackView是Autolayout的高级用法,帮你简化各种约束。属性distribution大概相当于是大小,alignment是排列,space是间距。核心便是方便垂直或水平排布多个subview,拖一个之后在其中添加子视图都会自动按照你给stackview设置好的效果进行排布。它的removeArrangedSubview(_:)只是告诉Stack View不再需要管理subview的约束。而subview会一直保持在视图层级结构中直到调用removeFromSuperview把它移除。也可在stackview约束不够时给子视图添加约束。UIStackViewDistributionEqualSpacing, UIStackViewDistributionEqualCentering是用于stackview高度确定,subview的高度也确定,想让subview比较均匀地分布在stckview中。均匀分布的方法不同,所以有2个选项。UIStackViewDistributionFillProportionally根据intrinsicSize自动按比例排列,UIStackViewDistributionFillEqually是指子视图高度或宽度都一样,UIStackViewDistributionFill就是填充,stackView要固定高,且约定除最后一个子视图的各个其它子视图的高度约束使最后一个不用设置高度约束就能刚刚好填充整个,如果没有设置stackView的高度,则给定所有子视图的高度,让其自动计算stackView的整体高度。设置stack view的抗拉伸卡压缩优先级是没用的因为stack view没有intrinsicContentSize。如果修改stack view内部元素和stack view外部元素的位置关系,要么捕获约束代码修改要么修改其抗拉伸或抗压缩的优先级。

ContentHuggingPriority 阻止控件被拉伸变大 ContentCompressionResistancePriority阻止控件被压缩变小。注意:IB中当前的IntrinsicWidth都是基于你当前xib支持intrinsic内容计算出来的尺寸。

// Compression Resistance
View.height >= 0.0 * NotAnAttribute + IntrinsicHeight
View.width >= 0.0 * NotAnAttribute + IntrinsicWidth
// Content Hugging
View.height <= 0.0 * NotAnAttribute + IntrinsicHeight
View.width <= 0.0 * NotAnAttribute + IntrinsicWidth

你可能感兴趣的:(Autolayout 你理解的够深刻吗(1))