前言:这篇文章是笔者在项目中对布局技术进行技术选型和应用的相关介绍,供大家参考。
&& [self.buttonscount] > 0)
{
UIButton *button = self.buttons[0];
[button autoPinEdgesToSuperviewEdges];
}
else
{
[self.buttonsautoMatchViewsDimension:ALDimensionWidth];
[[self.buttonsfirstObject] autoPinEdgeToSuperviewEdge:ALEdgeLeft];
UIButton *previousView = nil;
for (UIButton * btn inself.buttons)
{
[btn autoAlignAxisToSuperviewAxis:ALAxisHorizontal];
[btn autoPinEdgeToSuperviewEdge:ALEdgeTop];
[btn autoPinEdgeToSuperviewEdge:ALEdgeBottom];
if (previousView)
{
[btn autoPinEdge:ALEdgeLefttoEdge:ALEdgeRightofView:previousView];
}
previousView = btn;
}
[[self.buttonslastObject] autoPinEdgeToSuperviewEdge:ALEdgeRight];
}
}
这里对一组button(其数量是变化的)设置了约束,它们宽度固定,水平排列,两两相连,左右都顶到了view的最边缘。
对于一般的view来说,4个约束可以固定一个view。可以想象一下,你的view能否同时满足这几个条件,满足这几个条件以后它是不是就动不了了。
框架使用最佳实践:
学习和研究第三方库中的示例代码和api说明,能够帮助我们快速的掌握其api使用;如果有必要可以深入其源代码了解其中的细节。一般来说,其示例代码中的api调用方式是相对标准和安全的,值得我们参考和借鉴。
One more thing(关于autolayout的错误调试:)
autolayout错误会打印如下:
Unable to simultaneously satisfy constraints. Probably at least one of the constraintsin the following list is one you don't want. Try this: (1) look at eachconstraint and try to figure out which you don't expect; (2) find the code thatadded the unwanted constraint or constraints and fix it. (Note: If you'reseeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer tothe documentation for the UIView propertytranslatesAutoresizingMaskIntoConstraints) ( "<NSAutoresizingMaskLayoutConstraint:0x887d630 h=--&v=--& V:[UIButtonLabel:0x886ed80(19)]>", "<NSAutoresizingMaskLayoutConstraint:0x887d5f0 h=--&v=--& UIButtonLabel:0x886ed80.midY == + 37.5>", "<NSAutoresizingMaskLayoutConstraint:0x887b4b0h=--& v=--& V:[UIButtonLabel:0x72bb9b0(19)]>", "<NSAutoresizingMaskLayoutConstraint:0x887b470h=--& v=--& UIButtonLabel:0x72bb9b0.midY == - 0.5>", "<NSLayoutConstraint:0x72bf860V:[UILabel:0x72bf7c0(17)]>", "<NSLayoutConstraint:0x72c2430UILabel:0x72bfad0.top == UILabel:0x72bf7c0.top>", "<NSLayoutConstraint:0x72c2370UILabel:0x72c0270.top == UILabel:0x72bfad0.top>", "<NSLayoutConstraint:0x72c22b0V:[UILabel:0x72bf7c0]-(NSSpace(8))-[UIButton:0x886efe0]>", "<NSLayoutConstraint:0x72c15b0V:[UILabel:0x72c0270]-(NSSpace(8))-[UIRoundedRectButton:0x72bbc10]>", "<NSLayoutConstraint:0x72c1570UIRoundedRectButton:0x72bbc10.baseline ==UIRoundedRectButton:0x7571170.baseline>", "<NSLayoutConstraint:0x72c21f0 UIRoundedRectButton:0x7571170.top== UIButton:0x886efe0.top>" )
这里的约束看起来很难理解,应该是打印了类似VFL的约束表示。
我在项目中引入了NSLayoutConstraint+Description,重写了其description方法,这样在出错时可以容易的阅读当前出错的约束情况,加以鉴别。
附录:Autolayout出现前的iOS布局技术
关于旋转屏:
对于iphone应用开发者来说,绝大部分应用都是不需要支持旋转屏幕的;苹果的系统应用倒是有几个支持转屏(不过也主要是简单列表的布局,支持起来比较容易)。Iphone的长宽比例相差较大,因此如果要得到一个比较良好的体验,横屏和竖屏的布局一般都需要重新设计,由此带来了巨大的工作量;从用户体验来说也看不到支持横屏的必要性。因此,对于iphone应用来说,绝大部分应用都是不支持旋转屏幕的。大家可以看一下手机里的流行应用(微信、支付宝、网易新闻等),可能只有一些视频类应用的个别页面会支持转屏(播放视频横屏体验更佳)。
而对于iPad来说,其长宽比例较为接近(4:3),且苹果一开始就建议iPad应用开发者适配横竖屏以提升用户体验(横屏使用iPad对用户来说很平常,这点和iphone差别较大)。因此,对于iPad开发者来说,因为转屏场景的存在,布局适配一直是开发中需要注意的一个重点问题。
固定frame写法:
写死frame来布局,在只有320*480一套分辨率的时候非常happy; frame无需计算; 在iphone5推出之前(2012年9月发布),写死frame来布局UI是非常方便快速的;而对于iphone开发者来说,一般不需要考虑屏幕旋转的问题(上面我们已经说了,大部分app是锁定屏幕方向的)。这个时代的iphone 开发者是非常幸福的(android开发者需要适配碎片化的分辨率)。但iphone5、iphone6、iphone6plus带来的分辨率碎片化让固定 frame写法增加了很大的工作量,且代码难以阅读和维护。
Autoresizing技术:
就是在创建视图的同时给出其相对于父视图的“对齐方式与缩放系数”,即autoresizingMask。当父视图发生变化时,通过每个子视图的 autoresizingMask即可自动得出子视图的位置。
然而autoresizingMask的问题在于:
1. 其描述界面变化规则不够灵活,很多变化规则根本无法精确描述。autoresizingMask缩放比例是UIKit内部计算的,开发者无法指定缩放比例的精确值;且一般情况下,距离往往比比例更加精确(这点大家和设计同学沟通的时候应该有体会)。
2. 变化规则只能基于父视图与子视图之间,无法建立同级视图或者跨级视图之间的关系。
总结:Autoresizing用来简单的指定和父view之间的关系还是比较方便的。其在我们当前的项目中使用的也比较多,但它的局限性决定了它只能作为frame布局的辅助,应用于一些简单场景,对于复杂多样化的布局力不从心。在autolayout问世以前,通过autoresizing也可以处理一些简单页面的旋转屏布局(在细节要求不高的情况下)。