Android是一个运行在移动终端上的操作系统,跟传统PC最大的不同所在就是移动终端的资源紧缺问题“比较”明显,当然对于一些屌丝机型,应该用“非常“来形容才靠谱。所以经常会出现在一些比较缺乏青春活力的老型机上,运行一些软件被异常终止的情况;然而作为互联网厂家来说,广大的屌丝机用户肯定是一大笔用户资源,这是能放弃的市场吗?!当然不行o(╯□╰)o,所以我们要尽可能得提高软件的效率来赢取客户的回眸一笑了,屌丝也是客户!
这篇博客主要介绍如何在UI设计上提高效率,减少资源的利用,毕竟在终端资源短缺的今天,效率始终为王。我们评判一个UI界面不是认为有多复杂才给力,或者说有多炫才靠谱,一个简约而又不平凡的高效UI界面才是一个灰常牛逼的界面设计。
引入
在android应用中,采用硬编码方式编写界面并不是一个提倡的方法。当然硬编码编写的界面比基于XML文件的软编码界面高效灵活一些,但是非常不容易维护,错综复杂的代码更会让程序埋雷重重,说不定哪天就把应用炸的惨不忍睹。所以如果非常必要非常肯定要采用代码编写硬编码界面之外,其他情况还是采用易于维护的XML来编写比较好。
所以文中对于UI优化设计归结到底也就是对XML布局文件的优化设计。
在谷歌给我们的开发环境中,存在这么一个非常好用的工具——hierarchyviewer,估计很多人都没搭理过这个藏在偏僻角落的小工具吧;它能非常容易的帮我们分析UI界面的结构和构造效率,这个工具的位置就在sdk/tools/文件夹。
楼下上图:

大家好,我是图~
这是分析的是一个布局上只有一个TextView组件的XML界面,图告诉我们,构造这个界面总共用了四个组件,也就是需要绘制四次组件,自然每一次绘制组件都需要耗费资源。
下面步入狂拽酷炫吊炸天的主题部分。。。。
尽量用最少的步骤完成布局
我是社会好青年,我为国家省资源;当然作为组件来说也需要这个觉悟,每个组件的绘制都会多多少少耗费终端的资源。所以我们在这里可不能听老祖宗的话:韩信点兵多多益善了,精兵简政才是UI设计的唯一出路。不相信?行!下面就开始给个对比的例子。
假设项目需要搞这么一个按钮:
这不简单吗?几行代码不是分分钟的事情吗?
1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
<div class="line number10 index9 alt1">
10
</div>
<div class="line number11 index10 alt2">
11
</div>
<div class="line number12 index11 alt1">
12
</div>
<div class="line number13 index12 alt2">
13
</div>
<div class="line number14 index13 alt1">
14
</div>
<div class="line number15 index14 alt2">
15
</div>
<div class="line number16 index15 alt1">
16
</div>
<div class="line number17 index16 alt2">
17
</div>
<div class="line number18 index17 alt1">
18
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`<RelativeLayout`
</div>
<div class="line number2 index1 alt1">
` ``android:layout_width=``"wrap_content"`
</div>
<div class="line number3 index2 alt2">
` ``android:layout_height=``"wrap_content"`
</div>
<div class="line number4 index3 alt1">
` ``android:gravity=``"center"` `>`
</div>
<div class="line number5 index4 alt2">
` ``<Button`
</div>
<div class="line number6 index5 alt1">
` ``android:id=``"@+id/button1"`
</div>
<div class="line number7 index6 alt2">
` ``android:layout_width=``"wrap_content"`
</div>
<div class="line number8 index7 alt1">
` ``android:layout_height=``"wrap_content"`
</div>
<div class="line number9 index8 alt2">
` ``android:background=``"@drawable/btn_backgroup"`
</div>
<div class="line number10 index9 alt1">
` ``/>`
</div>
<div class="line number11 index10 alt2">
` ``<ImageView`
</div>
<div class="line number12 index11 alt1">
` ``android:id=``"@+id/imageView1"`
</div>
<div class="line number13 index12 alt2">
` ``android:layout_width=``"wrap_content"`
</div>
<div class="line number14 index13 alt1">
` ``android:layout_height=``"wrap_content"`
</div>
<div class="line number15 index14 alt2">
` ``android:layout_alignParentLeft=``"true"`
</div>
<div class="line number16 index15 alt1">
` ``android:layout_centerVertical=``"true"`
</div>
<div class="line number17 index16 alt2">
` ``android:src=``"@drawable/header_back"` `/>`
</div>
<div class="line number18 index17 alt1">
`</RelativeLayout>`
</div>
</div>
</td>
</tr>
</table>
</div>
也别急着看代码,多累多伤眼睛呀,直接上个hierarchyviewer里面的图来瞧瞧呗 
一个小小的按钮就用了3个组件来绘制,这就是3N的复杂度了呀,如果有5个这样的按钮就要15个组件,如果有10个按钮就要有30个,如果有N++个,哎呀妈的,不敢想象下去了。既然这样,我们是不是应该考虑一下优化优化,翻翻资料我们发现原来是可以不用这么多组件来实现的这个按钮的。 1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`<Button`
</div>
<div class="line number2 index1 alt1">
` ``android:id=``"@+id/button1"`
</div>
<div class="line number3 index2 alt2">
` ``android:layout_width=``"wrap_content"`
</div>
<div class="line number4 index3 alt1">
` ``android:layout_height=``"wrap_content"`
</div>
<div class="line number5 index4 alt2">
` ``android:background=``"@drawable/btn_backgroup"`
</div>
<div class="line number6 index5 alt1">
` ``android:drawableLeft=``"@drawable/header_back"`
</div>
<div class="line number7 index6 alt2">
` ``android:gravity=``"center"`
</div>
<div class="line number8 index7 alt1">
` ``android:padding=``"10dp"`
</div>
<div class="line number9 index8 alt2">
` ``/>`
</div>
</div>
</td>
</tr>
</table>
</div>
按照国际惯例,二楼上图 
还是原来的按钮,还是原来的味道,复杂度从3N降低到N!!!你敢说这样的效率你不想去提升???? **小结一个:**在我们设计UI布局时,应该从使用尽量少的组件的前提下入手,由于系统组件的封装比较完善,把多个简单的组件交由一个复杂一点的组件来实现,是可以得到比较好的效率的。因为每个组件都得需要独自进行绘制过程,多个组件绘制浪费的资源不仅仅谋害了我们的应用,更深深打击了用不起高端机的屌丝用户的自尊心——”他妈的,这软件又不能用!“。 你不干活?把你辞了。 我们还记刚开始给的一个图吗?我们在布局中使用的到仅仅是一个TextView,而RelativeLayout貌似啥子活儿都没干的样子。。。。。。 
我们从来都不提倡吃空饷不干活,软件界的潜规则也是这样的。出于构建和谐社会的正义感,我们当然不能坐视RelativeLayout这种站着茅坑不拉屎的流氓行为,所以我们就需要借助一个解决措施——标签,它能帮我们干掉一些不需要的根节点。为了拥有更好的即视感,所以我用了一个更为复杂点的布局(其实一点都不复杂)、、 主布局XML文件: 1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
<div class="line number10 index9 alt1">
10
</div>
<div class="line number11 index10 alt2">
11
</div>
<div class="line number12 index11 alt1">
12
</div>
<div class="line number13 index12 alt2">
13
</div>
<div class="line number14 index13 alt1">
14
</div>
<div class="line number15 index14 alt2">
15
</div>
<div class="line number16 index15 alt1">
16
</div>
<div class="line number17 index16 alt2">
17
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`<FrameLayout xmlns:android=``"http://schemas.android.com/apk/res/android"`
</div>
<div class="line number2 index1 alt1">
` ``android:id=``"@+id/layout1"`
</div>
<div class="line number3 index2 alt2">
` ``android:layout_width=``"match_parent"`
</div>
<div class="line number4 index3 alt1">
` ``android:layout_height=``"match_parent"`
</div>
<div class="line number5 index4 alt2">
` ``>`
</div>
<div class="line number6 index5 alt1">
` ``<ImageView android:id=``"@+id/image1"`
</div>
<div class="line number7 index6 alt2">
` ``android:layout_width=``"match_parent"`
</div>
<div class="line number8 index7 alt1">
` ``android:layout_height=``"wrap_content"`
</div>
<div class="line number9 index8 alt2">
` ``android:src=``"@drawable/bg"`
</div>
<div class="line number10 index9 alt1">
` ``/>`
</div>
<div class="line number11 index10 alt2">
` ``<com.net168.text.MyLayout `
</div>
<div class="line number12 index11 alt1">
` ``android:id=``"@+id/layout2"`
</div>
<div class="line number13 index12 alt2">
` ``android:layout_width=``"match_parent"`
</div>
<div class="line number14 index13 alt1">
` ``android:layout_height=``"match_parent"`
</div>
<div class="line number15 index14 alt2">
` ``>`
</div>
<div class="line number16 index15 alt1">
` ``</com.net168.text.MyLayout>`
</div>
<div class="line number17 index16 alt2">
`</FrameLayout>`
</div>
</div>
</td>
</tr>
</table>
</div>
组合控件布局XML文件: 1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
<div class="line number10 index9 alt1">
10
</div>
<div class="line number11 index10 alt2">
11
</div>
<div class="line number12 index11 alt1">
12
</div>
<div class="line number13 index12 alt2">
13
</div>
<div class="line number14 index13 alt1">
14
</div>
<div class="line number15 index14 alt2">
15
</div>
<div class="line number16 index15 alt1">
16
</div>
<div class="line number17 index16 alt2">
17
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`<LinearLayout xmlns:android=``"http://schemas.android.com/apk/res/android"`
</div>
<div class="line number2 index1 alt1">
` ``android:layout_width=``"wrap_content"`
</div>
<div class="line number3 index2 alt2">
` ``android:layout_height=``"wrap_content"`
</div>
<div class="line number4 index3 alt1">
` ``android:orientation=``"horizontal"`
</div>
<div class="line number5 index4 alt2">
` ``>`
</div>
<div class="line number6 index5 alt1">
` ``<Button android:id=``"@+id/button2"`
</div>
<div class="line number7 index6 alt2">
` ``android:layout_width=``"wrap_content"`
</div>
<div class="line number8 index7 alt1">
` ``android:layout_height=``"wrap_content"`
</div>
<div class="line number9 index8 alt2">
` ``android:text=``"button2"`
</div>
<div class="line number10 index9 alt1">
` ``/>`
</div>
<div class="line number11 index10 alt2">
` ``<TextView android:id=``"@+id/text1"`
</div>
<div class="line number12 index11 alt1">
` ``android:layout_width=``"wrap_content"`
</div>
<div class="line number13 index12 alt2">
` ``android:layout_height=``"wrap_content"`
</div>
<div class="line number14 index13 alt1">
` ``android:text=``"text1"`
</div>
<div class="line number15 index14 alt2">
` ``android:textColor=``"#ff0000"`
</div>
<div class="line number16 index15 alt1">
` ``/>`
</div>
<div class="line number17 index16 alt2">
`</LinearLayout>`
</div>
</div>
</td>
</tr>
</table>
</div>
这个界面很丑的,不忍直视: 
丑归丑,我们还是需要继续用神器hierarchyviewer看看这个XML生成的界面结构图来探索一下丑女内心丰富多彩的世界~~~~~~~ 
我靠。。。。三个组件的布局竟然用了六层嵌套布局,瞬间有了一种大花姑娘嫁给老光棍的一种深深的浪费感。我们开始看图说话,第一层和第二层的组件是系统都会自动生成的,这个是板上钉钉没法商量的事情,除非你去底层跟他们好好谈谈。但是~但是这个第三层的FrameLayout和第五层的LinearLayout完完全全是在自我秀存在感而已,所以我们要狠下心做掉他们,怎么来呢?用标签。 由于标签只能作为根元素,所以我们可以将这两个根元素都稍加修改,如下: 主布局XML文件: 1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
<div class="line number10 index9 alt1">
10
</div>
<div class="line number11 index10 alt2">
11
</div>
<div class="line number12 index11 alt1">
12
</div>
<div class="line number13 index12 alt2">
13
</div>
<div class="line number14 index13 alt1">
14
</div>
<div class="line number15 index14 alt2">
15
</div>
<div class="line number16 index15 alt1">
16
</div>
<div class="line number17 index16 alt2">
17
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`<``merge` `xmlns:android``=``"http://schemas.android.com/apk/res/android"`
</div>
<div class="line number2 index1 alt1">
` ``android:id``=``"@+id/layout1"`
</div>
<div class="line number3 index2 alt2">
` ``android:layout_width``=``"match_parent"`
</div>
<div class="line number4 index3 alt1">
` ``android:layout_height``=``"match_parent"`
</div>
<div class="line number5 index4 alt2">
` ``>`
</div>
<div class="line number6 index5 alt1">
` ``<``ImageView` `android:id``=``"@+id/image1"`
</div>
<div class="line number7 index6 alt2">
` ``android:layout_width``=``"match_parent"`
</div>
<div class="line number8 index7 alt1">
` ``android:layout_height``=``"wrap_content"`
</div>
<div class="line number9 index8 alt2">
` ``android:src``=``"@drawable/bg"`
</div>
<div class="line number10 index9 alt1">
` ``/>`
</div>
<div class="line number11 index10 alt2">
` ``<``com.net168.text.MyLayout`
</div>
<div class="line number12 index11 alt1">
` ``android:id``=``"@+id/layout2"`
</div>
<div class="line number13 index12 alt2">
` ``android:layout_width``=``"match_parent"`
</div>
<div class="line number14 index13 alt1">
` ``android:layout_height``=``"match_parent"`
</div>
<div class="line number15 index14 alt2">
` ``>`
</div>
<div class="line number16 index15 alt1">
` ``</``com.net168.text.MyLayout``>`
</div>
<div class="line number17 index16 alt2">
`</``merge``>`
</div>
</div>
</td>
</tr>
</table>
</div>
组合控件布局XML文件: 1 <div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
<div class="line number10 index9 alt1">
10
</div>
<div class="line number11 index10 alt2">
11
</div>
<div class="line number12 index11 alt1">
12
</div>
<div class="line number13 index12 alt2">
13
</div>
<div class="line number14 index13 alt1">
14
</div>
<div class="line number15 index14 alt2">
15
</div>
<div class="line number16 index15 alt1">
16
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`<``merge` `xmlns:android``=``"http://schemas.android.com/apk/res/android"`
</div>
<div class="line number2 index1 alt1">
` ``android:layout_width``=``"wrap_content"`
</div>
<div class="line number3 index2 alt2">
` ``android:layout_height``=``"wrap_content"`
</div>
<div class="line number4 index3 alt1">
` ``>`
</div>
<div class="line number5 index4 alt2">
` ``<``Button` `android:id``=``"@+id/button2"`
</div>
<div class="line number6 index5 alt1">
` ``android:layout_width``=``"wrap_content"`
</div>
<div class="line number7 index6 alt2">
` ``android:layout_height``=``"wrap_content"`
</div>
<div class="line number8 index7 alt1">
` ``android:text``=``"button2"`
</div>
<div class="line number9 index8 alt2">
` ``/>`
</div>
<div class="line number10 index9 alt1">
` ``<``TextView` `android:id``=``"@+id/text1"`
</div>
<div class="line number11 index10 alt2">
` ``android:layout_width``=``"wrap_content"`
</div>
<div class="line number12 index11 alt1">
` ``android:layout_height``=``"wrap_content"`
</div>
<div class="line number13 index12 alt2">
` ``android:text``=``"text1"`
</div>
<div class="line number14 index13 alt1">
` ``android:textColor``=``"#ff0000"`
</div>
<div class="line number15 index14 alt2">
` ``/>`
</div>
<div class="line number16 index15 alt1">
`</``merge``>`
</div>
</div>
</td>
</tr>
</table>
</div>
PS:注意需要在组合控件的类中加上一句setOrientation(LinearLayout.HORIZONTAL)来保证自组件的水平排列。 继续用神器看看结构: 
呼呼呼~~是不是从六层降低到了四层结构,好一股小清新的感觉呀,我都感觉飘飘然了,自然效率的提升是毋容置疑滴。。。。。 小结一个:标签能百分百代替这个布局组件,对于不复杂的其他布局组件如线性布局等组合组件中,可以在继承子类中对其属性进行设置后也可以使用标签,标签不占资源,自然在生成界面时也不会生成对应的组件。另外需要注意一点是只能作为根元素,对于需要用inflate生成布局文件时,必须指定一个ViewGroup作为其父元素,并且要设置inflate的attachToRoot参数为true。(参照inflate(int, ViewGroup, boolean))。
|
|
|
|
|
|
💬 评论