iOS 我们不熟悉的自动布局(一).

昨天从<<iOS Auto Layout开发秘籍>>的书中看到了我们在实际开啊中不常用看到的VFL和系统的自动布局类.虽然我们的前辈们已经开源了masonry等自动布局框架,但是他们还是在系统的框架基础上进行的再次封装.因为系统的自动布局约束看起来并不是那么简约.代码量比较多.但是我们在使用第三方约束的时候就应该明白,我们系统约束到底是什么样的.今天就给大家带来系统的自动布局约束类.在此并不包括IB中的自动布局.

系统原生自动布局

1.系统原生的自动布局还有划分,一种就是masonry封装的

+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullableid)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c

如果你看过masonry的源码肯定会看到这个方法.因为他最终都是通过这个方法对需要约束的视图进行约束的.

还有一种就是我们今天分享的重点VFL.以前都只是听说过系统有这种布局方式但是从来没有用过.那么系统提供两种布局方式到底有什么异同啦.

第一种约束方式.

先来敲一段和masonry使用同样方式的约束吧.

首先我们定义一个视图让其距离left 64, right 64,top 64,bottom 64.

代码
效果

由于开发都用masonry所以系统的方法很多都是记忆很模糊.那么我们首先来看看系统的这些方法.

添加or删除约束

前两个是添加约束的方法,后面两个书删除约束的方法.

这两个方法很简单,一个参数是NSLayoutConstraint,一个是数组,但数组元素还是NSLayoutConstraint.这个就不多解释了.如果有人不知道NSLayoutConstraint,那么就说一下吧.

从字面意思就能看出来他到底是干什么的了.NS不多解释苹果老大哥的Foundation的标识例如NSArray.layout就是布局的意思.那后面这个是什么啦?然而这个就是我们的约束.

上面的方法是在UIView的分类中添加的,那结果就是只要你继承或间接继承都会有这个添加和删除的方法.

关键字:update

从上面这张截图中我们看到了每个方法中都有update这个关键字.那么我们的初步估计就是更新约束.或者是更新约束后更新视图.苹果的方法最大的特点是意思写在明面上,这也就要求我们在定义我们的方法时一定要能从方法名看出作用.

1.updateConstraintsIfNeeded调用这个方法会立即更新约束.

2.系统实际用来更新约束的方法

3.这个方法的调用的返回值决定是否去掉用系统实际更新约束的方法.作为正常布局的一部分.

4.告诉layoutView需要更新约束,在下次计算或者更新约束会更新约束

从上面的方法我们可以总结出以下几点.当我们在未来的某个时刻需要更新约束时,会首先调用setNeedsUpdateConstraints.这个方法.然后在某个时刻上调用updateConstraintsIfNeeded这个方法.这个方法调用会调用updateConstraints这个方法来完成正常的更新约束.

如果只是淡淡的调用updateConstraintsIfNeeded这个方法,可能并不会调用updateConstraints这个方法来更新约束.因为吐过视图上的约束可能还没有发生变化且没有标记需要更新.

系统在调用layoutSubviews时,就会调用updateContraintsIfNeeded,通过更新约束,用super view到subview的层次顺序,来计算frame,返向确定布局.

stackoverFlow上有关于改变约束的方法研究.

1.如果想立即改变约束,调用setNeedsLayout

2.吐过想改变view的一些属性如offsets可能会导致布局的改变,那么会调用setNeedsUpdateConstraints,更多的时候和面还需要加setNeedsLayout.

3.如果想立即改变布局,如会形成新的frame,那么需要在调用layoutIfNeeded.


系统中还有很多方法,就不一一介绍了.等到用到时在进行解释.

上面的布局只是一个简单的相对于self.view 的布局.那么两个视图应该怎样布局啦.

布局布标,view1和view2并排放置,view2的left距离view的right 15px.并且view1和view2等高等宽,并且centerY等于self.view的centerY.

同一个父视图布局两个左右间距

好了如果左右间距都可以了,上下间距也是可以的.这个留在后面给大家当练习吧.

在这本书上还知道我们如何修改有歧义的约束和寻找因为不正确约束导致视图丢失的方法.

1.规则不一致的约束.有这么一个经典的例子就是viewA是viewB宽度的三倍,viewB是viewA宽度的2倍.请用代码实现.

当然代码我相信大家都能写的出来.但是肯定会有人问这个约束规则能实现吗?

答案是肯定的:绝对能实现.也毫无歧义,因为它的表述是完全正确的.在viewA的宽度=viewB的宽度*3和viewB的宽度=viewA的宽度*2这两个规则中并没有指定到底这两个宽度是多少,如果都是0那么这条规则就完全成立.所以我们最终就会看到视图的约束宽度为0.

2.缺失约束也可能导致丢失视图

举个简单的例子,就以我上面的代码为例:初始化frame为0,0,30,30.那么我给的约束是高度等于80,距离父视图left 0,top也是0,那么这个视图会在self.view上出现吗.并不会!并且约束也不会报错.那么视图为什么不出现啦.还记着我们没意识图需要自己添加约束时,讲一个属性置为了NO.translatesAutoresizingMaskIntoConstraints.什么意思啦.当我们设置这个属性时,默认的初始值(0,0,30,30)已经被废弃了.因为宽度没有确定,系统不能确定视图的宽度到底是多少,因而导致宽度为0,导致不可见.

还有就是介绍一下,添加约束的方法吧.

+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullableid)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c

先来介绍几个参数吧

item:需要添加约束的视图

attr1:需要添加约束的属性,例如left,bottom,top.right,centerx,centerY.等.

relation:分为三种1.NSLayoutRelationLessThanOrEqual小于等于.NSLayoutRelationEqual等于.NSLayoutRelationGreaterThanOrEqual大于等于.

view2:item布局的参考视图

attr2:view2的left,right等属性.比如item的left相对于view2的right距离15.

multiplier:比例

constant:固定值,比如设定item的宽高时,如果不与其他视图参考.view2可以为nil.attr2可以为NSLayoutAttributeNotAnAttribute.

总结:view.attr1 = view.attr2*multiplier+constant.

第一种约束方式就讲到这.

VFL

可能很多人对VFL只知其名,但在现实中没用过.

就在今天让我们一起研究它,使用它.

可能对于上面的代码,我们的感觉是代码量好大啊,布局一个视图就这么多代码.那么当时图较多时,怎么办.苹果的工程师也想到了这个问题就出现了我们第二种布局方式:

Visual format language.

它和第一种的约束布局的区别主要在于代码量减少了.而且方法更加简单.先来看一段🌰吧.

举例self.view上下左右各64.

代码


效果

然后我们来分析代码:

+ (NSArray<__kindofNSLayoutConstraint*> *)constraintsWithVisualFormat:(NSString*)format options:(NSLayoutFormatOptions)opts metrics:(nullableNSDictionary *)metrics views:(NSDictionary *)views;

我们看到这个方法的返回值是一个数组.数组中是这个NSLayoutConstraint对象.

参数format:我们从上面的代码就可以看出约束都是写在format中的.an ASCII art-like visual format string

opts:文档中的大概意思是,属性的描述和布局的仿效都是对象并且在visual format 字符串中.

metrics:这个字典的键必须是visual format字符串 ,他的值必须是NSnumber对象.在visual format字符串中的常量都在这个字段中.

views:visula format字符串中出现的views,保存在这个子弹中,键也是visual format字符串.值是view object.

好了看完这个我们应该仔细看看visual format 字符串.

H:|-64-[view]-64-| 这个字符串的意思是:水平方向距离左边64,右边64.

V:|-64-[view]-64-|  这个字符串的意思是:垂直方向举例上边64,下边64.

那么高度和宽度怎么设置啦.

很简单:

修改约束




V:|-64-[view(==80)] 这个就是距离top 64 高度等于80.设置宽度类似 只需要将V改为H就表示为,水平方向距离左边64,宽度为80.

VFL最大的缺点是什么啦.他不能表示相对比例和相对居中的约束.


那么两个视图的布局该怎么设置啦.


效果


代码

改有很多关于VFL的用法,这里就不多介绍了,可以查看苹果官方文档和(http://study1234.com/autolayoutshen-ru-qian-chu-liu-chun-dai-ma-de-pian-zhi/amp/)


在介绍几个方法就结束今天的分享了:

//调用这个方法来判断视图的约束是否充分/是否有歧义.

hasAmbiguousLayout

//可以获得不同方向上的约束

- (NSArray<__kindofNSLayoutConstraint*> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axisNS_AVAILABLE_IOS(10_0);

//这个方法会随机改变视图的layout到另外一个有效的layout。这样我们就可以很清楚的看到哪一个layout导致了整体的布局约束出现了错误,或者我们应该增加更多的布局约束。

exerciseAmbiguityInLayout

//让视图知道下次布局时需要重新计算.

//[view invalidateIntrinsicContentSize];

//压缩阻力Size Inspector指定

//代码设置一个视图的压缩阻力.水平轴和垂直轴都需要分别设置.设置的值可以再1到1000之间,默认值为750;

//[view setContentCompressionResistancePriority:500 forAxis:UILayoutConstraintAxisHorizontal];

////代码设置一个试图的内容吸附优先级.默认值为250;

//[view setContentHuggingPriority:501 forAxis:UILayoutConstraintAxisHorizontal];

我在这里先解释一下压缩阻力和内容吸附.

压缩阻力.就是指保护其内容的方式,压缩阻力高的视图可以抵抗压缩,不允许内容被裁减.低的压缩阻力内容会被裁剪.虽然我们空间本身存在着压缩阻力.但是如果他的优先级较低.如果我们改变约束,将其宽度较小.它的内容就会被裁剪.要想不被裁剪我们可以手动修改他的重要性.

//[view setContentCompressionResistancePriority:500 forAxis:UILayoutConstraintAxisHorizontal];

内容吸附:视图的大小与内容大小匹配的原则.

较高的优先级不允许视图将其伸展.防止出现大片留白.较低的优先级允许被拉伸,出现大量留白.

[view setContentHuggingPriority:501 forAxis:UILayoutConstraintAxisHorizontal];

我们可以手动改变其优先级.确定是否允许被拉伸.

我们在设置约束时也可以设置约束的优先级.

约束的优先级
四种优先级

1000为最高.50为最低.

好了我们不怎么熟悉的自动布局就先说到这里.后面还会有关于自动布局的分享.例如自动布局的动画.IB中的自动布局等.

如果喜欢小编,可以点击关注,我会不定期的更新一些文章,也可以关注我的专题

本人联系方式:qq:513961360

vx:扫描下方二维码:

希望能有志同道合的好友加我.聊技术.聊生活都可以.

vx


email:513961360@qq.com

也可以加我们的qq群希望能与朋友们一起聊天和学习.群里还有很多iOS开发者,帮助我们解决问题,并且同时学习.

qq群号:580284575

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容