【iOS】 AutoLayout初步学习

张开发
2026/4/13 23:14:56 15 分钟阅读

分享文章

【iOS】 AutoLayout初步学习
AutoLayout初步学习AutoLayout的概念自动约束的含义自动约束的优点创建普通视图时自动转化约束坐标约束的条件确定坐标需要的条件AutoLayout使用方法关闭自动生成签名及其各个参数介绍attribute和relatedBy的类型介绍数组激活的写法实例代码现代约束库简介AutoLayout的概念自动约束的含义早期iOS屏幕只有一种尺寸直接用frame写死坐标就行但是现在设备迭代硬件屏幕的大小也不一样了直接写死坐标会造成不兼容的问题而AutoLayout就是不写死坐标而是根据你添加的约束进行计算将计算结果作为坐标每条约束本质上是一个方程item1.attribute multiplier × item2.attribute constant比如A的左边距离B的右边20单位就是A.left 1.0 × B.right 20系统会将所有约束联立求解算出每个视图的frame就像是进行解方程虽然每个边和父视图的关系加起来有很多但只需要解出来宽高和左右上下坐标四个未知量所以四个方程即可约束是规则frame是结果。自动约束的优点规则定好之后父视图尺寸怎么变子视图都会跟着重新计算始终保持正确的相对关系。比如你写距左边20父视图宽300时子视图有280的空间父视图宽600时子视图自动有580的空间。这样就不用频繁的更改子视图在父视图中的布局创建普通视图时自动转化约束用代码创建视图时系统默认开启了AutoresizingMask的布局系统。简单理解就是你可以给视图设置一些弹性规则告诉它在父视图变化时如何伸缩。例如view.autoresizingMaskUIViewAutoresizingFlexibleWidth;// 代表子视图随父视图的宽方向大小变化而伸缩可设置的规则有这几种值含义UIViewAutoresizingFlexibleWidth宽度跟随父视图伸缩UIViewAutoresizingFlexibleHeight高度跟随父视图伸缩UIViewAutoresizingFlexibleTopMargin上边距弹性变化UIViewAutoresizingFlexibleBottomMargin下边距弹性变化UIViewAutoresizingFlexibleLeftMargin左边距弹性变化UIViewAutoresizingFlexibleRightMargin右边距弹性变化这里的弹性变化就是当父视图变化的时候子视图的大小也会变化并且“吃掉”变化的那部分而变多或变少什么都不设置的话默认行为就是frame完全写死父视图怎么变它都不动。这个的问题在于没办法描述复杂的相对关系。系统会自动把AutoresizingMask的规则翻译成几条AutoLayout约束。但这些约束是系统自动生成的不受你控制如果同时又手写了自己的约束两组约束就会打架布局就乱了所以我们在手动写AutoLayout的时候需要先关闭这个方式系统生成的和我们写的冲突后面会有介绍坐标约束的条件确定坐标需要的条件AutoLayout的目标是推导出视图的四个值x、y、width、height。只要这四个值都能推出来约束怎么组合都行组合是否合法左 右 上 下四边宽高都能算出来不需要再写宽高左 上 宽 高经典写法左 上 右 高宽能从左右推出来左 上 宽高不知道缺约束类似于三个方程解不出来四个未知量约束给少了就会导致系统报warning视图位置不确定这时候需要添加条件约束给多了或者矛盾了会让系统报error需要根据需要修改约束此外AutoLayout只负责算出视图的矩形框不管框里的内容。内容超出框之后clipsToBounds NO会溢出显示clipsToBounds YES会直接裁掉超出的部分。AutoLayout使用方法关闭自动生成刚刚提到过用代码写AutoLayout时第一件事是关掉系统的自动转换不然系统自动生成的约束和你手写的会冲突view.translatesAutoresizingMaskIntoConstraintsNO;这行写在addSubview:前后都可以但必须在activateConstraints:之前签名及其各个参数介绍[NSLayoutConstraint constraintWithItem:item1// 要约束的视图子视图attribute:attr1// 这个视图的哪个属性relatedBy:relation// 等于 / 大于等于 / 小于等于toItem:item2// 参照的视图父视图attribute:attr2// 参照视图的哪个属性multiplier:1.0// 倍数通常写1.0constant:20];// 偏移量对应回方程就是item1.attr1 1.0 × item2.attr2 20 // item1的attr1属性可能是宽高等是item2的相同属性加20个单位的结果如果是给视图设置固定宽高不需要参照其他视图toItem传nilattribute传NSLayoutAttributeNotAnAttribute表示方程右边没有参照物。attribute和relatedBy的类型介绍常用的NSLayoutAttribute值含义NSLayoutAttributeLeft / Right左边 / 右边NSLayoutAttributeTop / Bottom上边 / 下边NSLayoutAttributeCenterX / CenterY水平中心 / 垂直中心NSLayoutAttributeWidth / Height宽度 / 高度NSLayoutAttributeNotAnAttribute无参照用于固定宽高NSLayoutRelation的三个值值含义NSLayoutRelationEqual等于NSLayoutRelationGreaterThanOrEqual大于等于NSLayoutRelationLessThanOrEqual小于等于数组激活的写法创建NSLayoutConstraint对象只是写好了规则必须激活才会生效。有两种方式// 单条激活[constraint setActive:YES];这样写的话就要对每一条约束都执行一遍setActive比较麻烦// 批量激活[NSLayoutConstraint activateConstraints:[c1,c2,c3,c4]];activateConstraints:接收一个数组对里面每条约束逐个激活。数组只是个容器不同视图的约束也可以放在同一个数组里一起激活只要约束之间不冲突就行这个方法会对数组里的约束一一进行运行激活注意activateConstraints:必须在addSubview:之后调用不然没办法得到两个视图之间的关系实例代码在屏幕中间创建一个蓝色方框内部居中显示一行文字-(void)viewDidLoad{[superviewDidLoad];// 创建蓝色方框UIView*blueView[[UIView alloc]init];blueView.backgroundColor[UIColor blueColor];blueView.translatesAutoresizingMaskIntoConstraintsNO;//关闭自动生成[self.view addSubview:blueView];[NSLayoutConstraint activateConstraints:[//这里是字面量创建数组的写法// 宽200[NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeWidth//宽relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute//代表不参照multiplier:1.0constant:200],// 高100[NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight//高relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0constant:100],// 水平居中参照self.view[NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeCenterX//中心x坐标relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0constant:0],// 垂直居中参照self.view[NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeCenterY//中心y坐标relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0constant:0],]];// 文字标签UILabel*label[[UILabel alloc]init];label.textHello AutoLayout;label.textColor[UIColor whiteColor];label.translatesAutoresizingMaskIntoConstraintsNO;//依旧关闭[blueView addSubview:label];// label加到blueView里表明视图关系// label不需要宽高约束因为有字体等内部计算宽高[NSLayoutConstraint activateConstraints:[// 水平居中参照blueView[NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeCenterX multiplier:1.0constant:0],// 垂直居中参照blueView[NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeCenterY multiplier:1.0constant:0],]];}现代约束库简介初步学习到这里仅作了解后续内容笔者会继续学习补上原始的NSLayoutConstraint API功能完整但每条约束都要写一大串实际项目里挺繁琐的。苹果后来提供了更简洁的写法Anchor API通过视图的anchor属性链式添加约束是目前最主流的纯代码AutoLayout写法VFLVisual Format Language用字符串描述约束如H:|-20-[view(200)]看起来直观但没办法描述视图间的对齐关系现在基本被Anchor API取代

更多文章