上一篇我们讲了约束简单使用,但是在开发过程中远远是不够用的。这篇我们开始进行约束的进阶。
约束的进阶
约束的修改
进阶练习1
下面有个需求是这样的
A是B宽度是2倍,高度相等,并且两者占满整个屏幕。
横屏如图16-1所示:
竖屏如图16-2所示:
这样的约束我们如何进行添加呢?这个时候你就会发现,根据以上的知识点,你是不能实现这个效果的。这就要我们用到下面要讲的内容约束的修改。
那么首先我们需要让他能够进行修改,这样宽度的比例2:1,能够让他修改的只有等宽的约束,那么我们先把等宽等高的约束添加后,然后再对他进行修改。效果图如图17-1所示:
那这个约束的添加如图17-2所示:
那么这个约束添加完后的效果就编程了这个样子如图17-3所示:
那么现在他们2个宽度就建立起了关系,就是等宽的关系, 那么现在我们就可以根据这个关系进行修改,修改后就能变成我们需要的效果。如果要修改约束的话,我们就需要引入一个新的概念:
First Item =(<=、>=) Multiplier × Second Item + Constant;
苹果公司推出的控件位置的概念,无论是那个控件,我们都可以根据这个公式来让控件固定位置。那么这个公式是什么意思呢?
控件A的位置等于(=、>=、<=)控件B的位置*倍数加上多少像素。
那么这个公式在我们约束中,也是可以找到它的位置的。
我们添加的所有约束都可以通过clear进行删除。我们也可以删除其中一个约束重写添加,我们所有的约束都可以在这个位置找到,选中其中一个已经添加过约束的控件,如图18-1所示。
你可以选中其中一条约束通过delete进行删除。如果想要修改的话,我们以上已经给大家讲过通过Edit也可以进行修改,那么如果想看到刚刚给大家说的公式的话,大家要选中其中一个约束双击进入,就可以看到了。
我们根据上面的需求,需要修改宽度的比例,那么我们找到宽度的约束。如图18-2所示:
双击进入后,如图18-3所示:
这个就是给大家说的公式:
First Item =(<=、>=) Multiplier × Second Item + Constant
这里给大家详细说明下每个选项卡所代表的含义:
First Item:(id firstItem 属性).(NSLayoutAttribute firstAttribute 属性),其中的 firstAttribute 属性是可选的。
Relation:NSLayoutRelation relation 属性,有三个选项可供选择:Less Than or Equal(<=)、Equal(=)以及 Greater Than or Equal(>=),默认是 Equal(=)。
Second Item:(id secondItem 属性).(NSLayoutAttribute secondAttribute 属性),其中的 secondAttribute 属性是可选的。
Constant:CGFloat constant 属性,常数,可以手动输入,用以对约束进行调整。
Priority:UILayoutPriority priority 属性,优先级,默认值为1000,可以手动输入,一般不做修改。
Multiplier:CGFloat multiplier 属性,系数,可以手动输入,用以对约束进行调整。
Identifier:NSString *identifier 属性,约束标识。
每一个选项我们知道了所代表的含义,那么修改起来就变的简单起来,我们继续完成以上的约束,我们需要修改宽度倍数。那么我们要修改的值就是Multiplier。如图18-3所示:
修改后enter就能直接进行修改了。大家不妨随便改成其他值,看下效果。(ps:注意1/2,和2的区别。这里需要知道相对概念,A是B宽度的2倍,B是A宽度的0.5倍)。
进阶练习2
练习1中有没有感觉约束的修改很帅呢?接下来趁热打铁我们继续练习,A,B,C高度都是100,A,B,C占满屏幕,A的宽度是C的3倍,B的宽度是C的2倍。效果图如图19-1所示。
那么这样的约束通过练习1,我们可以很清晰思路,先把A,B,C先变成等宽的约束,实现的约束如图19-2所示:
更新后约束,效果显示如图19-3所示:
然后我们修改下约束,选中A控件,查看约束,找到A和B,A和C的宽度约束。如图19-4所示:
我们理下思路,A和C的关系是1:3,B和C的关系就是2:1。那么这里的约束,只有A和C,A和B的关系,没有B和C的关系。那么如果A和B的关系是3:2的话,那B和C的关系不就是2:1了吗。知道了这样思路,我们现在先对A和C的宽度约束先修改。如图19-5所示:
然后再点下A,回去选择A和B的宽度约束进行修改。如图19-6所示:
这样修改完成后,我们就可以直接得到我们刚刚需要的效果了。
进阶练习3
刚刚的的练习是修改了Multiplier,接下来我们开始修改
我们现在有这么一个需求,A和B控件占满了整个屏幕,但是A比B多了100像素。效果图如图20-1所示:
还是和之前一样,我们如果要想让A和B宽度上建立关系,这样我们才能进行修改。我们先将A和B等宽,然后就变成了之前的操作。然后修改他的约束,让A比B多100像素。这里不再演示那个约束的添加。我们直接看修改约束的位置。如图20-2所示:
我们这里修改了Constant的值,这么这张图所代表的意义就是:B是A的宽度是响度,但是B比A的宽度少了100像素。
进阶练习4
以上的所有练习都是控件能够根据屏幕进行适应的。现在我们做一个稍难点的练习,控件的大小是固定的,但是控件之间的间距是自适应的。效果图,竖屏下如图21-1所示:
横屏下如图21-2所示:
这样一个效果,如果想用约束来实现的话。添加约束如下:
A控件约束添加如图21-3所示:
B添加约束如图21-4所示:
然后让B和父视图的垂直方向对齐。如图21-5所示:
然后我们就可以得到刚刚我们想要的效果了。然后我们考虑个问题。这是三个控件,我们可以利用父视图中心线,如果是四个控件我们如果处理呢?
进阶练习5
效果和练习4是一样的效果,只是控件的个数是4个。直接看下效果图吧,竖屏如图22-1所示:
横屏效果如图22-2所示:
这样一个需求,我们用以上的知识来实现,恐怕是很让人恶心,那么这种效果在开发过程中,还是经常需要的。那这样的效果我们需要在控件上做下手脚。我们需要在每个控件中插入一个占位的控件,让他能够实现自适应间距效果。直接看图大家会明白的更多。如图22-3所示:
这样一来,应该有很多人已经要明白我的做法了。 (PS:我在这里给大家一个建议,这种在开发过程中,添加约束过程中,千万要把控件的变的足够小,就像上图一样,原则就是不要让每个控件有叠加的效果,如果一旦控件重叠在一起,系统默认相对的控件就会变的很怪异,这样你在添加约束的过程中,会变的格外的麻烦。)
然后,我们一起看看这个约束如何添加。首先ABCD 这四个控件的大小是相同的。我们可以通过command多选这四个控件 把他们的大小给固定住。如图22-4所示:
然后中间填充的lable,我们也是大小相同的,只不过,他们的高度是固定的,但是宽度是不固定的,我们可以吧高度设置成1,然后再修改他的隐藏属性,让用户看不到这个效果。添加约束如图22-5所示:
这样每个控件的大小就可以告一段落了。然后我们添加位置的约束,其实位置的约束就很好加了,只需要没个空间的上左右为0。然后更新下约束就可以了。添加约束如图22-6所示:
更新下约束,update Frames,使用快捷键‘alt’ + ‘command’ + ‘=’
然后我们就得到我们想要的效果了。如图22-8所示:
剩下的操作就是把lable隐藏,文字删除就可以了。接下来,我们要讲一个约束添加有点特殊的控件ScrollView
ScrollView 的 约束添加
我们使用代码创建 ScrollView 的时候,都必须要给定它的contentSize 属性,但是我们在可视化编程时并没有对这一属性进行设置。所以,当我们以 ScrollView 作为参考控件给其上的控件添加宽高约束时,系统自然就会报错。解决问题办法也就是要给ScrollView通过约束的方式给他添加上contentSize才可以。我们在这里给实现一个简单的轮播图的功能,看看如何实现。
步骤1,先给ScrollView的设置好约束。如图23-1所示:
步骤2:然后给ScrollView设置他的contentSize。我们都知道,contentSize是ScrollView的真正内容区域,如果我们想要设置这个ScrollView的contentSize就必须要给定ScrollView的内容层。那么在可视化编程中我们需要加入一个view在ScrollView上,然后给这个view设置约束。这一步就是给他指定内容层。如图23-2所示
步骤3:这里的view就是我们scrollview的内容层,然后我们再设置这个view的约束,这里再添加的约束就是给他制定contentSize的大小。这里大小,我给他设置成三倍的屏幕宽,也就是scrollview宽的三倍。高度和scrollview的高度相等。这一步是为了scrollview的contentSize设置添加约束。同时选中scrollview和view添加约束,如图23-3。
步骤4:上一步做完约束的红色错误就得到解决,这样一来,目前contentSize只是和当前scrollview的大小是相同的,然后我们修改下约束,把他的宽度设置三倍的scrollview宽。选中View层修改约束。如图23-4所示:
然后双击进入修改约束。把倍数修改为3倍。如图23-5所示:
修改后,大家可以看到view的大小已经超出了屏幕的外部。这样我们的scrollview的约束就已经添加完成了。剩下要做的就是把你的轮播图上的imageview添加上去,给imageview设置约束就可以了。
步骤5:填充轮播图控件。这里我用imageview代替。如图23-6所示:
然后更新下Frame就能得到轮播图的效果了。如图23-7所示:
约束如何实现动画
在我们用可视化编程时,公司的项目可能会存在动画的效果。而动画咱们在这章不再啰嗦。我们在这里举个UIView动画。来颜色下约束的动画如何实现。
UIView动画我们如果是代码实现的话,是修改了控件的frame,可是在我们使用可视化编程后,大家就不要把frame当成一个约束来看待了,约束是约束,frame是frame,他们2个不是相等的。也是不能相等的。也就是说,如果我们用的可视化编程的话,就要用UIView来修改约束,而不是frame。
现在有一个需求,在viewcontroller上 有一个view。在视图将要出现的时候,我需要给让这个控件由屏幕外滑动到屏幕内的位置。这样一种动画如果要实现的话,我们看看如何实现。
我们先把控件添加约束,让这个控件在屏幕外部。添加约束如图24-1。
这里的上约束我给的是负值,这样控件就在屏幕的外部了。现在我们想一个问题,如果现在让你把这个控件的约束修改到屏幕的外部,大家会怎么做,找到上边距的约束然后双击进入到约束的详情,修改他的Constraint。如图24-2所示:
那这样的话,动画效果就没有办法添加了。那我们刚刚修改的这个值用代码实现的话,就可以这样实现。
步骤1:找到上间距约束,把他拖拽成属性。(ps:当你点击左侧栏的约束时,右边视图中的约束条会变亮,这样在选择的时候就不容易选错了)如图24-3所示:
找到后,点击二环就可以给他拖拽成属性了。 (ps:按住control往interface中拖拽,然后出现这样一个效果后松手)如图24-4所示:
然后给你的属性起一个名字如图24-5所示:
这样一来,属性就生成了。然后我们开始代码修改他。回到我们ViewController.m中。
这个NSLayoutConstraint的对象,里面包含了我们之前提到的倍数+像素值,也就是我们之前提到的公式,在这个对象中我们都可以得到他。那么我们现在可以在写代码了。
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[UIView animateWithDuration:1 animations:^{
self.topLayout.constant = 200;
}completion:^(BOOL finished) {
}];
}
写完后,大家运行后发现动画并没有效果,控件是闪出来的,并没有动画的效果,那是因为我们没有给他更新约束。想想我们当初是不是在约束添加完成后做了刷新Frame的动作,但是这个动画没有实时的刷新,这样的话动画就得不到效果了。我们只需要添加一行代码就能结果这个问题。
[self.view layoutIfNeeded];
我们需要让他的根视图上让约束重新加载下。最后的代码是:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[UIView animateWithDuration:1 animations:^{
self.topLayout.constant = 200;
[self.view layoutIfNeeded];
}completion:^(BOOL finished) {
}];
}
这样动画效果就实现了。
约束宽度自适应效果
在开发过程中,有一种效果A控件的宽度是自适应的,B控件的宽度是固定的,B一直依附A的右侧。如图25-1,图25-2。
这样一个效果,如果用约束来实现的话,大家想想如何实现。
思路:左侧控件的右侧约束应该>=右侧的宽度。
我们一起先把左侧控件的约束定位适应屏幕的宽度,然后再修改的他的约束。左侧控件约束添加如图25-3所示:
这里的约束是针对父视图约束添加的。这样的话左侧的宽度是当前屏幕的宽。然后我们修改他的右侧约束,让他给右侧控件空出位置,也就是我们需要让右侧的约束>=右侧控件的宽度值。(右侧控件宽度我们给固定的20像素)
找到右侧约束如图25-4所示
修改右侧约束值,让其>=20像素,给右侧控件留出20像素。如图25-5所示:
这样一来,右侧永远只能到距离右侧边距20像素的位置就不再扩伸。最后我们把右侧的约束添加上就行了。(ps:让右侧控件相当于左侧控件约束添加)如图25-6所示:
然后刷新下Frames,就能得到我们需要的效果了。我们可以根据这个原理来实现另外的一个效果。
约束的进阶篇就介绍到这里了。