在实际开发中如何尽可能的减少层级、减少控件数量,并达到同样的视觉效果?本文记录开发过程中的实践。
如大众点评APP的首页:
显然第2种方式能够省掉 ImageView。
还有一种情况,还是拿我常用的大众点评 APP 中的页面作为例子,见下图:
"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与文本一起居中显示),但是我们却可以利用这一点实现上述布局。
经常用到横线,最直观的实现方法是放一张图片,其实这张图片可以省掉。
同样以大众点评APP的页面为例:
background="@drawale/bg_line"
其中 bg_line.xml :
<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 的矩形区域显示出来,看起来就是一条横线。
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(".color.deep_gray) + ">回复");
Spanned colon = Html.fromHtml(".color.link_color) + ">:");
Spanned body = Html.fromHtml(".color.text_color) + ">" + content + "");
Spanned richText = (Spanned) android.text.TextUtils.concat(spannableString, replyText, spannableString, colon, body);
textView.setText(richText);
tv.setMovementMethod(LinkMovementMethod.getInstance());
注意:
Html.fromHtml(string.replace("\r\n", "< br>").replace("\n", "< br>")).replace("\r", "< br>"));
<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 标签的库,具体见 https://github.com/NightWhistler/HtmlSpanner;
使用 Cmd + Alt + L(Mac),Ctrl+Alt+L (Windows)快捷键格式化 layout 代码,使得属性排列更加规范。
更多信息请参考 该网站。
控件类型 | 前缀 | 示例 |
---|---|---|
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 |
简单的工程建议使用上述前缀来区别文件的类型;
复杂的工程,建议以 module_ (如,个人中心模块的前缀为 account_,account_ic_launcher_calendar.png)作为前缀命名,公用的资源可以使用 base_ 或 common_ 作为前缀,这样命名有如下好处:
如果使用现有的控件特别是 layout 不能很多好的满足需求,我们可以自定义 View 完成。
比如微信头像墙的这个效果:
我们可以用 LinearLayout 实现,每一行都是一个 LinearLayout,但是这样层级较多(当然,盲目的减少层级也是不推荐的,因为 view 的绘制过程是由 meassure、layout、draw 三个过程完成的,层级会减少 draw 的时间,但是可能会增加 meassure 的时间,甚至得不偿失)。
我们也可以自定义一个 layout,在水平方向上放置子 view,空间不足时自动换行。