在新项目中使用Xib有一段时间了,遇到了不少的问题,也收获了很多的奇迹,最让我惊叹的就是使用熟练之后的界面开发速度,完胜Android那种XML方式的半吊子可视化界面开发工具。这里把使用心得汇总一下,希望能帮到大家。
一、Xib的使用深度
StoryBoard不是我的菜,毕竟VC之间的逻辑关系和跳转都比较复杂,甚至有时还得实现自己的栈管理,我更喜欢只是纯页面开发的时候使用可视化工具,就像Android的XML一样。感谢苹果,XCode的可视化工具比Android那个半吊子强太多了。
Xib中页面元素与VC中的事件关联我通常自己来通过addTarget的方式手动做,一方面是因为Android中这么做习惯了,另一方面事件注册的可变性太大,VC下面有时候还会分成更小单元粒度的Controller,就像Android中的Fragment一样。
二、Xib的基本原则
1、怎么样唯一确定一个View的布局?
只要直接或者间接确定x,y,width,height这四个值就可以了。这就是Xib的中心思想。
确定x和y的方式有很多种,这里举几个常见的例子:指定View在Parent中横向居中就是确定x的值,竖向居中则是确定y的值。指定相对于上方或下方View的距离就是确定View的y值,相对于左方或右方View的距离,就是确定View的x值。同时指定View距离其左方和右方View的距离,就可以同时确定x和width,而同时指定View距离其上方和下方的View的距离,就可以同时确定y和height。
2、支持定制
对于Xib中的一个View,可以指定其Custome类,这样就把具体实现交给继承了UIView的那个类了。这样,就可以对系统提供的任何View进行扩展,再通过Xib布局在页面上。
3、代码与Xib混排
Xib中可以包含定制的View,而代码生成的View中也可以添加通过Xib而Load进内存的View。
4、Xib中View的确切布局时机
在Xib中做页面布局时,只是指定了一系列的Constraints,并由IB对这些Contraints进行预览。那这些页面中的View到底是在什么时间点布局呢?准确地说,是viewWillAppear之后和viewDidAppear之前。在这之前,Xib文件的根View默认是600*600的,并没有根据Constraints在不同的Size Class下的表现进行layout计算。也就是说,想得到布局完成的View树并进行查看或操作,至少要到viewDidAppear中。
补充于2015.10.12
在一个使用AutoLayout布局的ALView中,使用代码增加了一些计算好frame的subView,等效果出来后,subView的frame可能会被ALView改变,因此,有必要把ALView的AutoResizesSubViews设置为NO。
对于通过loadNamedXib加载到内存中的View,必须手动指定其frame中的width和height,然后再通过addSubView的方式添加到现有的View树中,使用Xib表示的View在布局时,是以600*600的默认宽高进行的。
5、根View宽高不确定
我们在使用xib要时刻牢记。对于做过Android的同学来说,可以简单地把xib的根View理解成一个RelativeLayout。xib的根View的宽高是在真正程序运行到布局时才会参考当前的Size Class确定下来。所以,除非特别必要,不要使用绝对值来确定x,y,width,height的值。
6、Size Class
根据当前设备横屏、竖屏,还是手机、Pad,Xib把它们归为不同的Size Class,我们可以通过切换Size Class,让View在不同Size Class下展现不同的特性。比如,手机横屏和竖屏下,用户头像的位置分别位于屏幕上方和屏幕左方。
三、工具
可以看看这篇文章“如何使用View Debugging”,通过这个调试工具可以看到View的层级关系、边界等很详细的信息。
四、动态位置调整
这方面有一个很经典的场景,就是在经典的登录界面中,页面中主要的View从上往下依次是用户名输入框、密码输入框、校验码输入框、登录按钮。默认情况是没有校验码输入框的,这个时候登录按钮要紧挨密码输入框,一旦用户的登录触发安全策略,导致校验码输入框弹出来之后,登录按钮就要下移,给校验码输入框腾出位置来。
这在Android中可以使用Vertical的LinearLayout很轻松地布局出来,但在iOS中是没有现成的View可以做到动态调整子View位置的。只能使用稍微笨一点儿的方式,在代码中找到对应的Constraints,修改其Constant值。
这个时候需要注意,如果明确指定一个View的width和height等Constraints,那这个Constraints是属于这个View的。决定View的x、y,或间接决定width、height的其它Constraints都是在View的superView中的。不要找错了地方。
五、动态宽高
有的时候,我们可能需要根据View中的内容来动态调用一个View的宽高,如文章的Title,字数越多,Label越宽。这种情况就需要使用content hugging和content compression resistance这两个属性了。其详细的解释可以看看官方文档。
六、多练
这个是最高原则。我在新项目中除了少数几个很特殊的控件自己实现之外,99%的布局都使用Xib来完成,一开始不太熟悉稍微有些慢,等熟悉了之后,开发速度非常快。如今屏幕尺寸这么多,这AutoLayout比手工通过代码获取屏幕宽高计算View布局的方式快了岂止一个数量级。多练习,会出现奇迹的。