原文链接 Android Layout大点兵
智能手机催生了移动互联时代,现如今移动应用越来越成为最为核心的终端。而GUI页面是移动互联终端的标配,做好一个GUI页面,是非常重要的,能极大的提升用户体验和用户满意度。安桌生态,自古以来(没那么久,自安桌流行以来)在GUI方面就逊于水果生态,GUI页面的美观程度,操作流畅度以及动效的优美程度,水果生态是远好于安卓生态的。好消息是近几年的版本谷歌在这些方面做了大量努力,几乎追平与水果平台的差距。特别是在support libraries(现在是叫AndroidX)里面加入一些在各方面都远好于标准API中的UI组件,现在只要稍加努力就可以做出与水果一样,甚至更炫酷的GUI页面。
现在,对于安卓开发人猿来说,做GUI页面时选择很多,比如实现一个简单页面,可以用FrameLayout,也可以用LinearLayout,实现列表时可以用ListView,也可以用RecyclerView,面对纷繁复杂的需求以及众多的选择,到底该如何做选择,就成一个令人头痛的事情,今天就对Android布局进行一次大点兵,聊聊这些布局到底该如何使用。
注意:这里面提到 的布局的意思是承担主页面的ViewGroup,比如页面的根布局。而不是指一些具体的内容渲染View(如TextView之于Text,ImageView之于Image)。
简单和够用
同样一个页面,实现的方式可以千奇百怪,就好比经典的“Hello,world”,就可以有很多种实现方法。文字肯定是用TextView,那么根布局用什么呢?可以用FrameLayout,可以用RelativeLayout,可以用LinearLayout,当然也可以用ListView,甚至是RecyclerView。对于产品同学来说,需求都可以实现了。但是可以并意味着就应该。
从工程和研发的角度来讲,实现方式要以够用和简单为首要原则,功能实现了仅仅是第一步,后续的维护成本是极其高昂的。代码首要是写给人看的,简单或者说优雅的实现方式,才能方便其他人理解,才可以降低维护成本。除此之外,代码也是写给CPU的,执行的性能和效率也是要考虑的因素,重型武器虽然也能杀死一只蚂蚁,但它耗费的资源相较于一根树枝来说,就大太多了。
过早优化是万恶之源,同理过于复杂的实现方案也是灾难之源。开发人猿要把简单和够用作为首要的原则。针对页面布局更是如此,能用普通的就用普通的,能用简单的就用简单的,功能实现了就可以,但是要尽可能以简单和便于理解作为标准。
布局大点兵
要想做出合适的选择,首先就需要对常用的布局进入了解,知道每种布局的优势和缺点,不同布局之间的区别,这样才能做出最佳的选择。
对于安卓的布局,可以分为三类,一是结构性布局,二是集合性布局,区别就在于数据是否是一个无限集合。比如像ListView它就是一个集合性布局,因为它可以显示无限个数据,只要往adapter里塞数据,列表就可以展示;而像LinearLayout就是一个结构性布局,虽然理论上它也可以塞无限个子view,但只能手动的塞,且性能会极其的差,毕竟它设计出来的目的,是沿一个方向排列一定数量的子View。
需要注意,不能简单的以可否滑动来作为布局的区分分类,因为结构性的布局,假如子View较多的话,外面包一层ScrollView也是可以滑动的;而集合性布局,假如数据 少于一屏的话,也是不可以滑动的。重点还是在于数据量。
结构性布局
FrameLayout
简单易用,重点应用场景是层叠,在水平和竖直方向都没有约束,因此它最适合用于页面的根布局,比如手机窗口的根节点,Activity的根节点,Dialog的根节点等等,都是FrameLayout。
因为FrameLayout重点在于层叠,所以有时候可以做一些Canvas级别的裁切,比如实现圆角,这时也可以用FrameLayout,对FrameLayout的draw时去做裁切,然后整体效果就是做出了圆角,这对于一些不方便做圆的View有帮助,比如像SurfaceView,本身不方便做圆角,因此可以面其上面包一层FrameLayout,就可以实现圆角。
LinearLayout
某一个方向的简单堆叠。最为方便的便是按比例排列,不过性能有影响。居中和对齐不如RelativeLayout方便。
RelativeLayout
特点就是每个子View必须指定相对于其他View的条件参数,以实现布局。强大且复杂,可以完全实现FrameLayout和LinearLayout。
特点是对于居中和对齐的支持很好,缺点就是性能差。且容易牵一发动全身。
GridLayout
非常适合表格形的页面,就好比计算器之类的,具体使用方法可以参考之前的文章。要点就在于子View呈表格形排列,且大部分的子View的尺寸是一致的,这时就可以考虑使用GridLayout。
ConstraintLayout
这个是AndroidX中增加的大杀器,使用方法可以参考这篇文章,可以胜任意的非集合性布局场景,可以完全替代前面提到的几种布局。
但为了避免滥用重武器,建议用ConstraintLayout替代LinearLayout和RelativeLayout就好。
集合性布局
ListView
集合性布局的典型代码,非常适合列表性数据。特点是简单易用。缺点是只能垂直方向滑动,每个条目元素的布局不宜复杂,并且对动画的支持不那么友好。当每个元素条目的布局非常简单时(如 就是简单的icon+文字)并且没有眼花聊乱的动画时,那么用这个也足够了。
GridView
与ListView类似,只不过是以表格形态来展示,简单易用,当每个无素条目较简单时,用这个比较合适,同样只支持垂直方向滑动。
RecyclerView
AndroidX中的集合性布局的大杀器,它重点在于Recycler,在渲染层面做了较多的优化,且布局方式跟ViewGroup本身没关系,有各种布局管理器来实现不同样式的布局,并且对动画的支持,也就是说每个元素条目的进入退出的动画的支持非常友好。
缺点就是使用起来较麻烦,目前已经变成了集合性布局的标准实现,但其实有被滥用的嫌疑,很多对于元素条目非常简单的场景没必要用它的。
ViewPager
水平方向多页布局的标准组件。其实把它称作集合性布局,略迁强,因为很多时候它的数据量并不像前面那几位那样多。需要注意它的适用场景是有很多页需要横向滑动展示时,这里页的意思是,每一屏只展示一个元素条目。
如何选择一个合适的布局
首先,要对数据量做区分,看是选择结构性布局还是集合性布局,然后再依据页面的复杂程度来做具体的选择。
其次,核心的原则是够用和简单,不能为了用而用,简单的实现功能能节省大量的维护成本。
具体的指导原则是:
- 应用的根布局或者页面的根布局建议用FrameLayout
- 稍复杂的LinearLayout和RelativeLayout一定要用ConstraintLayout来做
- 如有可能,可以多多用ConstraintLayout
- 对于集合性布局,如果元素条目简单,且无动画要求,那就用ListView或者GridView吧
- 如有可能,可以多多用RecyclerView
- 水平方向多页展示,没得说就用ViewPager
参考资料
- Layouts
- Linear Layout
- Relative Layout
- Build a Responsive UI with ConstraintLayout
- Create dynamic lists with RecyclerView
- AdapterView