AutoLayout简介
AutoLayout
旨在替代Autoresizing
,所以在同一个项目中,AutoLayout
和Autoresizing
是不能共存的,二者只能选其一,如果你选择了AutoLayout
,那么Autoresizing
自动被屏蔽掉;如果你选择了Autoresizing
,那么AutoLayout
自动被屏蔽掉。XCode5
及其之后的版本,默认新建的项目就是使用AutoLayout
关于约束
约束概念
AutoLayout
主要是通过控件参照与约束实现,比如控件A相对控件B来说,控件A在控件B的正下方,间距为20px
每在xib
或sb
中对控件添加一个约束, 就代表添加一个约束对象。比如,给xib中的某个子控件A设置了宽度和高度、距离父控件上下左右之间的间距,就相当于给这个控件添加了6个约束,也就产生了6个约束对象
约束错误警告
- 红色箭头,代表约束错误,一般是缺少约束或约束冲突(例如375的屏幕宽度,你不能距离左边200,距离右边200,还要控件宽度100,肯定不行)
- 黄色箭头,代表约束警告,表示当前控件在xib中呈现的位置或者尺寸和程序运行后实际呈现的效果不一样,导致约束警告的原因往往是没有更新控件的约束,但并不影响其真实效果,也不会报错
注意:约束有错误,不代表运行会错误,约束错误同样可以运行
约束的规则
- 相对于父视图的约束,添加到父视图上
- 相对于另一个控件的约束,添加到其共有的父视图上
- 跨层级的约束,添加到其最上层的父视图上
- 自身的宽高等约束,添加到自身视图上
特殊控件的约束
UILabel
默认内容的显示方式是垂直居中的。如果用autolayout给UILabel
设置约束,只需要设置x
、y
、width
,无需设置height,UILabel
会自动包裹内容,并且随内容的多小而变化。如果我们通过约束给定了UILabel
的width = 100
,但是内容仍然少的可怜,不能包裹,可以把宽度设置为<=100
,此时,label
的宽高都能包裹住内容。高度的设置同理可证。 当然,我们也可以只给UILabel
设置x
、y
。但必须要保证UILabel
的text
属性有内容,否则UILabel
显示不出来(这是初学者经常犯的错误)。原因在于,UILabel
是根据内容自动调整宽度和高度,如果没有内容,那么宽度和高度就是0
,导致UILabel
无法显示。
AutoLayout用法
XIB
中设置AutoLayout
多个控件对齐处理
单个控件的处理
Safe Area
: iOS11中增加的,safe area
可以看作是系统在所有的 view
上加了一个虚拟的 view
, 这个虚拟的 view
的大小等都是跟 view
的位置等有关的(当然是在 iPhoneX上才有值) 以后在写代码的时候,自定义的控件都尽量针对 safe area
这个虚拟的 view
进行布局
Constrain to margins
: 默认会距边框16px
, iPhone6Pluse 准备的,一般都会去掉
User Standard Value
:使用标准的的值,而且这个值只有在是设置上下方向的时候才有用。默认的值其实就是距离 Bottom Layout Guide
,也就是上下基线。下基线就是距离视图最底部。上基线就是距离StatusView
下方的位置
User Current Canvas Value
:使用当前位置设置。默认为当前设置方向最近的一个View
,且没有覆盖遮挡的视图
注意:上下左右的间距和控件的宽度、高度配合使用,尽量不要冲突; 例如:375的屏幕宽度,你不能距离左边200,距离右边200,还要控件宽度100,肯定不行
建议:给了距离左边的间距,同时给出空间宽度即可,适用于lable
,textField
等控件,不考虑它到底距离右边多少;如果给了距离左右的间距,就不要给宽度了,适用于button
之类的控件。
更新、添加、清除约束
Selected Views
: 处理当前你选中View的约束问题,Clear Constraints
清除约束,会删除选中的视图的所有的约束
All Views in View Controller
:处理当前ViewController
里所有的View
的约束问题,Clear Constraints
会删除当前VC所有的约束
自适应布局(Trait Variations
)
Trait Variations
替换了的Size Class
。可以看到下面机型与自适应的尺寸匹配起来,变得更加直观
Device
:在Device
中,看到某个具体的机型,选择设备,很容易被误导以为特征变量会针对具体机型生效,其实并不是针对具体哪一个设备,而是相同sizeclass
的一类设备,所以添加特征变量是影响一类设备
Interface Style
:亮色或暗色的界面风格
orientation
:设备方向
Vary for Traits
:点击后会弹出选择Width
、Height
复选框,选择宽度、高度或两者,背景会变成蓝色,左边显示的设备也会变化,选择设备后,点击Done Varying
按钮
示例:
[图片上传失败...(image-a28823-1634197751423)]
一般组合有4种结果(wC hC
)、(wR hR
)、(wC hR
)、(wR hC
) (w
是width
h
是height
,C
是Compact
R
是Regular
)
(
wC hR
):它适用于一切尺寸的竖屏iPhone(
wR hR
):适用所有横屏、竖屏iPad(
wC hC
):适用于iPhone的横屏上(除了iPhone11、iPhone Plus等)-
(
wR hC
):适用于iPhone 11 、iPhone Plus的横屏等示例: 如果使用iPhone8 (
wC hR
)UI布局,且分类按钮选了Width,那么如果对iPhone8的UI进行修改,会使同为wC的设备比如(wC hC
)、(wC hR
)的UI产生改变 如果使用iPhone8 (wC hR
)UI布局,且分类按钮选了Height
,那么如果对iPhone8的UI进行修改,会使同为hR的设备比如(wR hR
)、(wC hR
)的UI产生改变 如果使用iPhone8 (wC hR
)UI布局,且分类按钮选了Width
和Height
,那么如果对iPhone8的UI进行修改,会使同为(wC hR
)的设备的UI产生改变
根据不同布局,不同分类选项,对相应的布局产生影响,总结如下:
UI布局 | Width | Height | Width & Height |
---|---|---|---|
CR | CR、CC | CR、RR | CR |
RC | RC、RR | RC、CC | RC |
CC | CC、CR | CC、RC | CC |
RR | RR、RC | RR、CR | RR |
在不同布局下,同一控件通过设置不同常数值实现相同效果,可以在配置在添加布局,而不是添加两个约束 [图片上传失败...(image-c44a00-1634197751423)]
在不同设备上修改控件属性,比如在iPhone竖屏上字体比较小,在iPhone横屏上字体比较大,这时候使用Vary for Traits
就没有效果了,我们只需要为控件属性增加布局,如果不需要点叉删除
[图片上传失败...(image-f20169-1634197751423)]
如果想指定尺寸选择一个新控件,可以在控件属性最下端,操作是类似,左边的加号指定尺寸,Installed
表示通用
-
修改约束
方式一:First Item
:第一个要设置的控件约束Second Item
:第二个要参照的控件约束Relation
:第一个控件与第二个控件约束值之间的关系-
Less Than or Equal
:小于等于 -
Equal
:等于 -
Greater Than or Equal
:大于等于
Constraint
:约束的偏移量Priority
:约束的优先级-
Required
(1000):默认优先级(高优先级) -
Required
(1000):中优先级 -
Required
(1000):低优先级
Multiplier
:约束值放大倍数-
Reverse Multiplier
:反转倍数(即 0.5 变为 2,4:3 变为 3:4) -
Convert to Decimal
:转换为十进制 -
Presets
:预设值(也可以不使用预设值,自己设置需要的倍数,如 0.5) -
1:1
倍 -
4:3:4:3
倍 -
16:9:16:9
倍
Placeholder
(Remove at build time
):编译时移除该约束核心公式:第一个
方式二:Item
的属性=(<=/>=)
第二个Item
的属性*Multiplier+Constant
-
-
预览(通过
PreView
可看到各设备预览)[图片上传失败...(image-a696d9-1634197751421)]
代码中设置AutoLayout
利用NSLayoutConstraint
类创建具体的约束对象
添加、删除约束对象到相应的view上
- (void)addConstraint:(NSLayoutConstraint *)constraint
- (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints
- (void)removeConstraint:(NSLayoutConstraint *)constraint
- (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints
复制代码
注意:
-
1.先禁止
autoresizing
功能,设置要添加约束的控件的下面属性为NO
testView.translatesAutoresizingMaskIntoConstraints = NO; 复制代码
-
2.添加约束之前,一定要保证相关控件都已经在各自的父控件上
[self.view addSubview:testView]; 复制代码
3.不用再给
view
设置frame
-
示例:
/*
- (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c
view1:要约束的控件
attr1:要约束的类型(上、下、左、右等等)
relation:与参照控件关系(小于等于、等于、大于等于)
view2:参照控件
attr2:要约束的类型(上、下、左、右等等)
multiplier:约束值放大倍数
c:偏移量
*/
//redView(10,10,300,100)
NSLayoutConstraint *xConstraint = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:10];
[self.view addConstraint:xConstraint];
作者:NewBoy
链接:https://juejin.cn/post/6983861948664250382
来源:稀土掘金