Android 布局优化

减少布局层级

  提升布局性能的关键点是尽量保持布局层级的扁平化,避免出现重复的嵌套布局。

利用View的特殊属性

  • 利用TextView的滑动属性来避免嵌套一层ScrollView

  如果页面需要使用TextView来展示文本信息,但是文本信息可能超过一屏,我们可以使用TextView的setMovementMethod()的方法来设置TextView的滑动。

TextView textView = findViewById(R.id.textView_tv);
textView.setMovementMethod(new ScrollingMovementMethod());

  设置了上面代码后,TextView就可以进行滚动了。还可以在xml文件中设置android:scrollbars =""属性来设置是否显示滚动条。
  注意事项:设置TextView可滚动以后,并不会让页面的显示超出一屏。TextView只是在它所占据的页面空间中滚动。

  • 利用TextView的drawableXxx属性来设置icon图标

  我们可以使用TextView的drawXxx属性来代替使用一个ImageView来设置文本周围的图标,以及使用drawablePadding属性来设置图标与文本之间的距离。属性如下:

android:drawableLeft="@drawable/imageXxx"
android:drawableStart="@drawable/imageXxx"
android:drawableRight="@drawable/imageXxx"
android:drawableEnd="@drawable/imageXxx"
android:drawableTop="@drawable/imageXxx"
android:drawableBottom="@drawable/imageXxx"
android:drawablePadding="20dp"

  注意事项:使用android:drawableLeft这几个属性的时候,需要注意设置的图标和文本的距离。我们使用android:drawablePadding=""属性来控制图标离文本的距离。drawablePadding属性可以为正值,如20dp,也可以是负值,-30dp。正值代表设置图标远离文本,负值代表设置图标靠近文本。默认情况下,图标会显示在控件的边缘,比如最左边或这最上边。如果控件设置宽或高为wrap-content,可以使用android:drawablePadding=""属性为正值来控制图标离文本的距离,一般情况下,我们使用这两个属性的场景就是这种场景。android:drawablePadding属性不区分上下左右,只要在某一个方向设置了android:drawableXxx,那么在这个方向,android:drawablePadding属性就会起作用,会把控件和图标之间撑开设置的drawablePadding属性的大小的距离,但是如果在某个方向没有设置android:drawableXxx,控件的大小并不会被撑开。而且,使用android:drawableLeft和android:drawablePadding并无法设置图标的大小。我们可以使用java代码来设置图标的大小。

//设置要显示的图标的大小;
Drawable drawable = getResources().getDrawable(R.drawable.play);
drawable.setBounds(0,0,100,100);
Drawable drawable2 = getResources().getDrawable(R.drawable.play);
drawable2.setBounds(0,0,100,100);
//设置要在哪个方向上显示图标;
textView.setCompoundDrawables(drawable,drawable2,null,null);
//设置文本和图标之间的距离;
textView.setCompoundDrawablePadding(100);

使用merge标签

  如果布局的最外层和它所在的父容器控件相同,那么使用merge标签可以减少一层布局嵌套。
  关于查看一个xml布局文件的标签嵌套,我们可以使用Android Studio自带的Layout Inspector。我使用的是3.6.1版本,在Android Stuidio菜单项Tools下面,连接要调试的手机,打开手机中要调试的应用页面,点击Layout Inspector,Android Studio会提示你选择哪个应用,选择你要调试的应用,然后就可以在Android Studio中看到布局界面的标签嵌套了。

  举个很简单的例子,如果我们使用的layout文件的根布局是FrameLayout布局,那么就可以直接使用merge来代替FrameLayout,因为DecorView中content内容使用的就是FrameLayout作为根节点的。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.ex.kang.view.ViewAllActivity">

  就可以使用下面的代码来代替上面的,其实也就是merge标签代替FrameLayout标签。

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.ex.kang.view.ViewAllActivity">

  当替换了标签以后,我们可以在Layout Inspector中查看新的xml标签布局,就能看到减少了一个FrameLayout标签,就减少了一个布局嵌套。

使用ViewStub标签延迟加载布局

使用ConstraintLayout

  ConstraintLayout可以认为是RelativeLayout布局的升级版,合理使用这个布局的属性,可以很好地优化布局嵌套。因为这个布局的讲解需要配合它的好多属性去讲,这就不进行细讲了。

减少过度绘制

  可以认为是GPU在同一个区域进行了不必要的多次绘制。大部分是设置多余的背景色和不可见区域的绘制导致的。

布局复用

使用include标签进行布局复用

  当我们的布局中有多个相同的布局时,可以使用include标签来进行布局的复用。

减少布局中的View

使用SpannableStringBuilder替换多个TextView

  多种不同大小、颜色或者图文混排需要显示时,我们往往会利用多个TextView来进行组合,但是某些效果通过一个TextView和SpannableStringBuilder配合就可以实现。详细的可以查看下SpannableStringBuilder的使用。

使用LinearLayout自带的divider属性实现分割线

  我们常见的一个场景是设置页面的多个功能入口之间是有分割线的,我们可以使用LinearLayout自带的divider属性实现分割线,而不是在布局中再额外添加View作为分割线。
  与分割线相关的属性如下:
divider:传入分割线的drawable,可以是一个图片,也可以是自己通过xml实现的drawable;
showDividers:分割线显示的位置,beginning/middle/end,分割对应头部、中间、尾部;
dividerPadding:分割线距离两边的间距;

使用Space控件进行合理的占位

-
-
-
-
-
-
-
-
-
-
-
-
-
-
------------------last line for now------------------