布局优化

官方链接
参考链接

布局优化的核心在于
1.减少布局嵌套
2.减少控件的使用
3.不能为了优化而优化,需要考虑到复用性和扩展性
4.开发与设计之间的协作性和规范性

1.图文优化

1.1

优化代码:利用drawableLeft配合drawablePadding

<TextView android:drawableLeft="@drawable/icon_1"
      android:drawableRight="@drawable/icon_4"
      android:drawablePadding="10dp"
      android:paddingLeft="10dp"
      android:paddingRight="10dp"
      android:textSize="16sp"
      android:text="我的卡券"
      android:background="@color/white"
      android:gravity="center_vertical"
      android:layout_width="match_parent"
      android:layout_height="50dp" />

注意事项:任何一种优化,都只适用于某一部分特定的场景。
如果后续业务有扩展,整体的结构还是需要进行调整。
例如”我的卡券”后面,需要展示用户有多少张劵。

这个时候,一个控件就感觉不够用了。

1.2

优化代码:
利用lineSpacingExtra属性(行间距,绝对值),默认是0
或者lineSpacingMultiplier属性(行间距倍数,相对值),默认为1.0f
考虑到适配的话,建议用lineSpacingMultiplier

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:drawableLeft="@mipmap/ic_launcher"
    android:drawablePadding="10dp"
    android:gravity="center_vertical"
    android:lineSpacingExtra="8dp"
    android:paddingLeft="25dp"
    android:text="揽件方式:上门取件\n快公司:顺丰快递\n预约时间:9月6日立即取件\n快递费用:等待称重确定价格"
    android:textSize="14dp" />

注意事项:同样,维护才是难点。如果在”揽件”和”快递公司”二者之间加入一个,需要点击的事件,或者是联系方式变成红色,并且可以点击,那么这种就还是需要进一步去调整。

1.3 TextView部分文字变色,并且部分范围可以点击。

//设置文字
SpannableStringBuilder text = new SpannableStringBuilder();    
String login = "登录即代表同意";
String protocol = "《用户服务协议及隐私权条款》";
style.append(login + protocol);
//设置部分文字点击事件
ClickableSpan clickableSpan = new ClickableSpan() {
      @Override
      public void onClick(View widget) {
              //doSomething
      }
  };
  //设置点击区域的位置
  text.setSpan(clickableSpan, login.length(), login.length() + 
  protocol.length(),Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
  //设置部分文字颜色
  ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.parseColor("#0000CD"));
  style.setSpan(foregroundColorSpan, a.length(), a.length() + b.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);              
  mTvLogin.setMovementMethod(LinkMovementMethod.getInstance());
  mTvLogin.setText(text);

1.4 使用Spannable

1
2
3
4
5
6
7
String text = String.format("¥%1$s  门市价:¥%2$s", 18.6, 22);
int z = text.lastIndexOf("门");
SpannableStringBuilder style = new SpannableStringBuilder(text);
style.setSpan(new AbsoluteSizeSpan(DisplayUtil.dip2px(mContext,14)), 0, 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //字号
style.setSpan(new ForegroundColorSpan(Color.parseColor("#afafaf")), z, text.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //颜色
style.setSpan(new AbsoluteSizeSpan(DisplayUtil.dip2px(mContext,14)), z, text.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //字号
tv.setText(style);

1.5 总结

综合上面四个demo,得到以下的总结:
任何一种优化,都有自己的使用场景
根据自身项目实际需求,弄出一个精简版的superTextview。
但是随后参照了淘宝和哔哩哔哩等热门APP,发现很多都没有这样去做。

例如哔哩哔哩的弹幕,因为高频率刷弹幕,所以优化处理,节省性能。


1
2
3
4
5
而作为一些基础view,则还是普通的写法。
当然也包括了淘宝的页面。
其实这一类的优化,都要考虑其适用场景。
如果是属于同一个层级的话,优化意义并不大。
如果涉及到布局嵌套了,那么就可以做一下对应优化处理。


账户余额这里就可以用精简化的supertextview,从而达到减少布局嵌套。

2.减少嵌套

原则:尽量保持布局层级的扁平化。
手机的”设置”==>开发者选项==>显示布局边界,可以看到对应的控件
不影响层级的情况下,尽量使用LinearLayout而不是RelativeLayout。因为RelativeLayout比LinearLayout更耗时,它会让子View调用2次onMeasure,LinearLayout在有weight时,才会让子View调用2次onMeasure。Measure的耗时越长那么效率就低。

如果非要是嵌套,那么尽量避免RelativeLayout嵌套RelativeLayout。估计也没人会这样做

3.Space控件

3.1 介绍

1
2
3
4
5
6
多个组件之间的缝隙,如果用View,则消耗性能。
使用过多的margin会影响代码的可读性。
所以,这里就推出space控件,用于组件之间的缝隙。
Space 是个轻量级的view,只占一点位置,而没有其他属性。
因为draw()是空实现,减少了绘制渲染,组件之间的距离使用Space会提高了绘制效率。
特别是对于动态设置间距会很方便高效,同时也因为他是个空实现,所以,设置背景是颜色无效的。

3.2 应用场景之一

3.3 注意事项

1
2
3
4
1.   Space的draw是个空实现,所以设置样式是无效的。
2. 有些时候,组件之间有缝隙,同时必须要设置颜色,如何优化处理?
从代码实现的角度,目前来说,只能写个控件来做
从团队规范性的角度,无论是前端 后台 设计师 产品之间 都是有对应的规范性,而不是随心所欲

4.利用LinearLayout自带的divider和showDividers

1
2
3
android:divider="@drawable/divider"
android:orientation="vertical"
android:showDividers="middle|end"

具体的divider,可以参照shape
android:showDividers有三种属性,
beginning //LinearLayout头部添加
middle //LinearLayout中间添加(即各child之间添加)
end //LinearLayout底部添加

divider的应用场景当然不仅仅只是线条,只要是包括drawable中的属性都可以。同样也考验一个团队的协同性和规范性。

5. include、merge 、ViewStub

include 略 只需要知道 可以调节大小,通常在title中用的比较多。

merge实际上就是结合include进行使用。可以减少布局嵌套,但是实际应用中,却用的非常少。

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<include layout="@layout/title"></include>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="标题" />

</LinearLayout>

而include中的根布局也是LinearLayout,此时,就可以用merge代替。

6.Recycleview的线条

1.Recycleview的分割线,不需要单独去写view,直接调用
mRvContent.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));

当然也可以直接继承DividerItemDecoration 自己自定义

因为这里是相同的item样子的线条。如果有不同item线条,将要如何处理。

2.布局优化都做完了,再结合项目中的自定义view的解耦。
还有uml图和时序图的学习。

可以通过那个检测工具来检测布局层级分布情况,然后再对其进行优化处理。
首页的推荐目前没有什么毛病,用Vlayout。除了分析源码加上各种调用,然后就是自己手写。加上市面各种adapter,还有自己封装recyclerview。包括分割线,是否需要下拉上拉的滑动默认栏。
最关键是要结合屏幕适配来做。
不可能是给固定坐标。

所剩问题
1.relativelayout和framelayout的区别
2.toolbar的讲解。

igding wechat
2018 依计行事 持续精进
坚持原创技术分享,您的支持将鼓励我继续创作!