1. 降低 ImageView 的数目

1.1 使用 TextView.drawableXXX

如大众点评APP的首页:


布局优化技巧笔记_html

注意红色框内的部分


红色框住的部分。由一张图片和它以下的文字组成,至少有两种实现方式:


  1. ImageView + TextView,图在上文字在下;
  2. TextView,设置 TextView.drawableTop=”xxx”。

显然第2种方式能够省掉 ImageView。

另一种情况,还是拿我经常使用的大众点评 APP 中的页面作为样例。见下图:


布局优化技巧笔记_android_02

注意最右边的箭头


我们能够用例如以下的布局实现:

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableRight="@drawable/arrow"
android:gravity="center_vertical"
android:text="查看所有网友点评"
android:textSize="16sp" />

除非 android:layout_width = “wrap_content”,否则即使把 android:gravity 属性改成 center,箭头仍然是居右的。这是非常恶心的地方,导致我们无法将文本和 drawable 一起居中(解决方法见 自己定义控件让TextView、Button的drawableLeft和drawableRight与文本一起居中显示),可是我们却能够利用这一点实现上述布局。

1.2 使用 layer-list 画线

经经常使用到横线。最直观的实现方法是放一张图片,事实上这张图片能够省掉。

相同以大众点评APP的页面为例:


布局优化技巧笔记_sed_03

注意“网友推荐”以下横线(右边的小手能够用1.1的方法实现哦)


当然能够用 ImageView 实现。

或者换种方法:将“网友推荐”所在的 layout 的 background 属性设置为:

background="@drawale/bg_line"

当中 bg_line.xml :

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#DADADA" />
</shape>
</item>
<item android:bottom="1px">
<shape>
<solid android:color="@color/white" />
</shape>
</item>
</layer-list>

2 个 item 画了 2 个层叠的矩形。下层矩形填充色是 #DADADA,上层矩形的填充色是白色。并且上层矩形的下边框比下层矩形的下边框高 1px,于是就有宽 1px、颜色为 #DADADA 的矩形区域显示出来。看起来就是一条横线。

2. 使用 ViewStub

3. 使用 merge

4. 使用 ClickableSpan


布局优化技巧笔记_android_04

注意红色框中不同颜色的文本


使用 ClickableSpan 富文本实如今同一个 TextView 中的文本的颜色、大小、背景色等属性的多样化和个性化。例如以下图红色框内是一个 TextView(也可能是多个 TextView),可是却有两种不同的颜色,这样的效果就能够用 Spannale 实现:

Spannable richText = new Spannale("<font color=#E3E5F3>Alan海波</font>回复<font color=#E3E5F3>大赞</font>:你走开···");
textView.setText(richText);

假设不仅颜色不同,还要对某些文字加入响应事件(如跳转链接等),能够使用例如以下方式:

String username = "Alan 海波";
String content = "你走开……";
SpannableString spannableString = new SpannableString(username);
ClickableSpan span = new ClickableSpan() {
@Override
public void onClick(View widget) {
// do sth.
}

@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(getResources().getColor(R.color.link_color));
ds.setUnderlineText(false);
}
};
spannableString.setSpan(span, 0, username.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);

Spanned replyText = Html.fromHtml("<font color=" + getColor(R.color.deep_gray) + ">回复</font>");
Spanned colon = Html.fromHtml("<font color=" +getColor(R.color.link_color) + ">:</font>");
Spanned body = Html.fromHtml("<font color=" + getColor(R.color.text_color) + ">" + content + "</font>");
Spanned richText = (Spanned) android.text.TextUtils.concat(spannableString, replyText, spannableString, colon, body);
textView.setText(richText);
tv.setMovementMethod(LinkMovementMethod.getInstance());

注意:


  • Html.fromHtml(string) 会将 string 中的 ‘\r’ 和 ‘\n’ 替换成空格,须要显式的将 ‘\r’(早期 Mac 系统)和 ‘\n’ (Unix 和 Max OS X)和 ‘\r\n’(Windows) 替换成 html 识别的 ‘< br>’,不替换的话,假设 string 中出现 “xx&xx\r” 形式的子串,会发生 IOException:

Html.fromHtml(string.replace("\r\n", "< br>").replace("\n", "< br>")).replace("\r", "< br>"));

  • 用 ClickableSpan 给 TextView 中的文本设置响应事件 a,再对 TextView 设置响应事件 b。在某些机型上点击文本时会同一时候触发 a 和 b;
  • 安卓原生只支持以下 HTML tag 标签:(

<a href="...">
<b>
<big>
<blockquote>
<br>
<cite>
<dfn>
<div align="...">
<em>
<font size="..." color="..." face="...">
<h1>
<h2>
<h3>
<h4>
<h5>
<h6>
<i>
<img src="...">
<p>
<small>
<strike>
<strong>
<sub>
<sup>
<tt>
<u>

有支持所有的 HTML tag 标签的库

5. 代码格式化

使用 Cmd + Alt + L(Mac)。Ctrl+Alt+L (Windows)快捷键格式化 layout 代码,使得属性排列更加规范。

6. 资源文件命名

很多其它信息请參考 该站点。

控件类型

前缀

演示样例

Action bar

ab_

ab_stacked.9.png

Button

btn_

btn_send_pressed.9.png

Dialog

dialog_

dialog_top.9.png

Divider

divider_

divider_horizontal.9.png

Icon

ic_

ic_star.png

Menu

menu_

menu_submenu_bg.9.png

Notification

notification_

notification_bg.9.png

Tabs

tab_

tab_pressed.9.png

图标资源的命名:

资源类型

前缀

演示样例

Icons

ic_

ic_star.png

Launcher icons

ic_launcher

ic_launcher_calendar.png

Action bar icons

ic_menu

iic_menu_archive.png

Status bar icons

ic_stat_notify

ic_stat_notify_msg.png

Tab icons

ic_tab

ic_tab_recent.png

Dialog icons

ic_dialog

ic_dialog_info.png

PopupWindow icons

ic_pop

ic_dialog_like.png

按压态的命名:

状态

后缀

演示样例

Normal

_normal

btn_order_normal.9.png

Pressed

_pressed

btn_order_pressed.9.png

Focused

_focused

btn_order_focused.9.png

Disabled

_disabled

btn_order_disabled.9.png

Selected

_selected

btn_order_selected.9.png

简单的project建议使用上述前缀来差别文件的类型。

复杂的project,建议以 module_ (如,个人中心模块的前缀为 account_。account_ic_launcher_calendar.png)作为前缀命名,公用的资源能够使用 base_ 或 common_ 作为前缀,这样命名有例如以下优点:


  • 格式整齐。易读性强;
  • 清理废弃资源文件时,比方使用 lint 来检查废弃资源时,方便划分责任范围;
  • 防止出现引用非本module资源文件的发生;

7. 自己定义 View

假设使用现有的控件特别是 layout 不能非常多好的满足需求。我们能够自己定义 View 完毕。

比方微信头像墙的这个效果:


布局优化技巧笔记_html_05

我们能够用 LinearLayout 实现。每一行都是一个 LinearLayout。可是这样层级较多(当然,盲目的降低层级也是不推荐的,由于 view 的绘制过程是由 meassure、layout、draw 三个过程完毕的。层级会降低 draw 的时间,可是可能会添加 meassure 的时间。甚至得不偿失)。

我们也能够自己定义一个 layout。在水平方向上放置子 view,空间不足时自己主动换行。