大家好。
请原谅我用了这样一个高调奢华张扬浮夸的标题。毕竟这是一篇设计相关的文章,为了表现本人的美学修养,为了营造良好的艺术氛围,我决定放弃『奥土雷奥特从入门到精通』『垃圾小波教你30分钟掌握设计大局观』『艾欧哀思布局看这篇就够了』这样土爆了的名字,而使用和我本人一样低调又有内涵的『设计美学』作为这篇文章标题。
UI 可以说是 iOS 开发中不可避免的一个重要环节。手撕还是拖拽的咸淡豆腐脑之争先放在一边,在这篇文章里我希望和大家分享一些我在使用 Auto Layout 开发 UI 时的想法。
亲爱的手写党们,请不要看到这里就关闭浏览器。文章虽然是关于 Auto Layout 的,但是其实最核心的部分是如何将设计稿中的像素转化为开发稿中的约束,而这点在所有开发场合中都是通用的。
『如何将设计稿中的像素,转化为开发稿中的约束。』这句话居然还押韵,我真是个天才。
Auto Layout 是一种通过约束规定页面组件的依赖关系后自动布局的 UI 编写方式。
本质上, Auto Layout 是规定了两个组件属性的线性关系。
|
关于 Auto Layout 的基础知识本文不再赘述,请参考阅读:
学完了 Auto Layout 的基础之后,Auto Layout 的学习其实才刚刚开始。
一个居中对齐的按钮,通过以下属性搭配就至少有16种组合:
不同的设计场景下有着不同的选择。如何用课本上学来的知识解决实际问题,如何优雅而高效的实现种种设计需求,这是我们需要考虑的问题。
在开始 Auto Layout 之前,首先要充分地理解设计稿。设计稿不仅仅是一堆花哨的切图和死板的标注,它是设计师努力思考的成果。
为什么这里是这个配色?为什么这里会有投影?为什么这里要加个蒙版?为什么这俩按钮的间距是20而不是30?为什么这个按钮是圆的而不是方的?
有些问题是有答案的,比如基本的色彩搭配,比如让页面更有层次感,比如为了更容易阅读。也有些是没答案的,可能只是设计师天马行空的想法和脑海里灵感碰撞的结果。但是这些都不影响你理解设计。理解了设计之后,你就不会翻那些忘了设背景色之类的低级错误了,因为你自己看效果的时候都会忍不住骂:『这文字没蒙版太难阅读了!』
理解设计的第一步是对设计稿整体的理解和分析。熟悉基础控件、熟悉常用配色、熟悉跳转流程,在脑海中对各个页面有个完整的印象。
以一个语音日记本为例:
这个应用非常简单,一共就2个页面,6个状态。大致浏览一边之后便会获取以下信息:
经过这样初步的分析之后,对整个页面的有了大致的了解,对布局和动效的处理也有了一个初步设计,同时对某些细节还有一些疑问,经过和设计师的沟通后,解决疑问点,然后开始开发。
我和设计师合作的时候是不需要设计师给标注的。因为他不知道我要什么,我其实也不缺什么。如果导出的是标准的 640 x 1136 设计稿,那我只要用系统自带的 Preview.app 就能看到我想要知道的任何数值。
我开发页面的流程是这样的:
为什么这样做,主要有以下几个原因:
所以我不会让设计师给我标注稿,因为我想要的东西,标注是给不了的。我想要的,是读懂他的心。
我理想中的设计与开发的合作,是灵魂上的高度统一,是思想上的心有灵犀,是感性设计和理性分析紧密结合旋转跳跃升腾交融后的智慧结晶。
怎么写着写着玄幻了,上面那句划去吧。
初步了解了设计稿之后,接下来就是实现的部分了。
我个人开发页面的流程大致如下:
当然这其中还有很多别的细节,比如是否需要 IBDesignable 、是否需要 Size Class 、是用 IB 写 CustomeView 还是 drawRect 里写、是用 CALayer 还是用 UIView 实现动画、要不要考虑 ChildViewController 等等。
回顾过去几年的 iOS 开发经历,我的所有应用最终基本都是通过 StoryBoard 或者 xib 实现的。有很多应用一开始是用代码写的,手撕过 Frame、Autoresizing Mask、Auto Layout 等原始代码,也用过 Mansory、SnapKit、PureLayout、CocoaUI 等第三方库,最后无一例外,统统被我改成了 IB 实现。在后期出新设计稿的时候非常高效,开发效率大幅提升。
当然啦,使用 IB 只是我的个人喜好,很多人也喜欢使用代码手撕页面,这没有任何问题。不管是 IB 拖拽还是手写代码, Auto Layout的设计理念都是通用的,主要是三方面内容:
在熟练掌握各种属性的基础上,深入理解上面三个方面的细节,最后融会贯通,便是我心中的 Auto Layout 最佳实践。
视图的层次是一个标准的树状结构。比如下面这个页面:
我们可以将页面进行分解:
使用 IB 拖拽的效果如下:
在一些复杂的场景中,通过透明的 UIView 将各个控件组织起来,可以让页面的层次更加清晰。不信看图:
清晰的层级关系、合理的组织结构、良好的命名规范,不管是手写代码还是 IB 拖拽,都是非常重要的基础素养。
有了层次基础,接下来就是同层级控件间的依赖关系。以顶部为例:
这样一个控件,主要就是左边的日期和右边的日历,应该如何设计才比较合理呢?依赖关系有以下几种设计方式:
我选择的方案是第一种,主要原因是:两个控件没有明显的主次关系,不需要相互依赖,只要控制间距即可。
最后就是选择最优的属性将控件之间的关系表现出来了。Auto Layout 提供了很多属性供我们选择,不同的属性适用于不同的使用场景,选择更合理的属性,可以大幅提高页面的可读性和可扩展性。
还是以前面的需求为例:
首先,先确定它们的对齐方式。从图中来看,日期应该左对齐,日历应该右对齐,所以使用 Leading 和 Trailing 设置对齐即可。
然后,确定它们的拉伸方式。这个方法就比较多了,主要有一下几种:
最终我的选择是方案三。原因如下:
综合上面三点,我再举另一个完整的例子:
在这个页面中,主要是纵向上的三个控件:
如何优雅的实现这个页面呢?
首先,将页面分解成3个大块:
将它们依次命名为:
然后设计依赖关系。主要问题在于,上中下三个部分的高度和 Y 坐标如何确立。
我的方案是:
上面的方案有没有问题?
有问题。
什么问题?
如果屏幕长宽比 1:1 ,那么可能把 GreetingView 挤了盖住底部的按钮,因为它没设置 Bottom ,如果 TopView 的高度超过了屏幕高度的 3/4 ,那文字就没地方放了。
但是这个问题需要解决吗?
不需要。因为如果屏幕的比例真的离奇到了这种程度,那么设计稿也是作废的。等真的到了那个时候,需要的不是更新约束,而是出新的设计稿。
我理想中优秀的页面开发是一劳永逸的,适配 iPhone 789JQK Plus Mini 各种也都只要调整小部分特殊情况而已,除非苹果出了正方形的屏幕的 iPhone 。从我个人往年的开发经验来看,这是可行的,基本上只要和设计师沟通好控件的依赖关系和自身状态,适配 iPhone 6 和 iPhone 6 Plus 是自然而然的事情。
对于 iPhone 4 那种小屏导致界面摆不下,那是一开始就该和设计师沟通的事情,双方讨论好控件到底是相对于屏幕(Stick to Bottom)还是放在可滑动的页面上(UIScrollView)上,这和控件的层级关系有关,不该在适配特殊机型时才开始考虑这些问题;对于 iPad 那种因为尺寸差异过大导致需要重新开发那又是另一码事了。
另外补充一点,设计师在设计页面的时候,也一定不要有 iPhone 6 或者 iPhone 4 的概念,因为页面设计不是针对某个像素值的,而是针对整体的布局和美感的。标注里的 20 30 40 其实不应该绑定不同分辨率的屏幕,而应该找出背后的设计逻辑,更合理地表现出来。
在此补充说明以下,文中的『更好』『更优』『更合理』等主观词语均是『在我眼中更』的缩写,不具有任何权威性,甚至可能不适用于你的团队,这都很正常。
正所谓,一千个人眼里就有一千个奥土雷敖特。欢迎大家沟通交流。
下面进入自编自导自演的 Q&A 环节。
UI 是廉价的,设计 Auto Layout 的时候花时间考虑这么多有意义吗?
有意义,原因如下:
StoryBoard 那么乱真的能用在公司项目里?
手写代码和 IB 如何选择?
正如前面的问题所述, UI 是最廉价的东西,不要把自己的生命浪费在手写代码 UI 上。我的观点是,应用的核心在于业务逻辑,至于 UI 到底是如何实现,除了一群程序员之外无人关心。
权衡利弊,充分考虑需求、团队、维护等问题,在合适的场合使用高效的方案。
很多人倾向选择代码写界面,主要因为以下几点:
针对以上问题,我的观点如下:
IB 维护起来会不会比手写代码复杂很多?
其实并不会,反而还会轻松很多,关键还是看团队成员的质量。
前段时间看到有人把所有 view 都放在了根视图里面,然后屏幕上就是海量 subview 海量 AutoLayout ,啊我的天呐!
前段时间看到有人吐槽 xib 里的 Auto Layout 删除之后会变成灰色而无法彻底删除,然后就是满屏的约束,啊我的天呐!
这就很尴尬了。
有些人没有层级观念,写什么都是乱糟糟挤成一团,那问题不在 IB ,而在于他自己本身写 UI 的经验和思考不足,就算用代码写 UI 也会有一样的问题。
有些人不了解 Runtime Attributes 不了解 IBDesignable 不了解 Size Class 然后在那里说 IB 烂透了,这我不能接受。最起码,你应该充分了解 IB ,学习 IB 里的各种技巧,并总结各种最佳实践之后,你才能真正体会到 IB 有多烂。
没错从某些角度来讲它是很烂, IBDesignable 经常卡死,Runtime Attributes 简直就是埋了个定时炸弹,Size Class 也并没有想象中好用,xib 文件打开一下居然就出现了改动,这简直太坑了。不过这些并不影响我使用 IB 开发。了解这些坑,然后继续利用 IB 中我觉得对我有价值的部分,它给我带来的价值远大于它的弊端。
你看你用 IB 就要考虑这么多问题,学习成本是不是比手写代码高多了?
文中提到的 Auto Layout 相关的观点并不是 IB 所独有,层级关系、依赖关系、属性选择,这些东西手写代码也是需要考虑的。如果你没考虑,呃,那可能是你想的太少了。
关于 IB 和 Auto Layout ,所有我想写的都在这里了。其实我一开始只想写 Auto Layout 的最佳实践,但是 IB 的部分却越写越多。
手写代码和 IB 拖拽各有优劣,希望各位可以冷静对待,因地制宜,择优而用。毕竟,适合自己的才是最好的。
我的心愿是,世界和平。
IB 党万岁