安卓常见布局

  • FrameLayout 所有子元素都叠放在左上角
  • LinearLayout 按照垂直和水平顺序依次排列子元素,尽量少用 layout_weight,会导致二次测量
  • TableLayout 为表格布局,适用于 N 行 N 列的布局格式
  • RelativeLayout 按照各个子元素之间相对位置完成布局
  • ConstrainLayout 功能更强大,通过各种约束,可以实现更加扁平化的页面布局

ConstraintLayout 布局

基本属性

layout_constraintLeft_toLeftOf          // 左边左对齐
layout_constraintLeft_toRightOf         // 左边右对齐
layout_constraintRight_toLeftOf         // 右边左对齐
layout_constraintRight_toRightOf        // 右边右对齐
layout_constraintTop_toTopOf            // 上边顶部对齐
layout_constraintTop_toBottomOf         // 上边底部对齐
layout_constraintBottom_toTopOf         // 下边顶部对齐
layout_constraintBottom_toBottomOf      // 下边底部对齐
layout_constraintStart_toEndOf          // 起始边向尾部对齐
layout_constraintStart_toStartOf        // 起始边向起始边对齐
layout_constraintEnd_toStartOf          // 尾部向起始边对齐
layout_constraintEnd_toEndOf            // 尾部向尾部对齐
layout_constraintBaseline_toBaselineOf  // 文字的底部线对齐,用于含文本的控件对齐基线
layout_constraintDimensionRatio         // 宽高比"2:1"、"H,2:1"或"W,2:1"

Barriar

android xml能修改图片颜色吗_android

<androidx.constraintlayout.widget.Barrier
    android:id="@+id/id_barrier1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:barrierAllowsGoneWidgets="true"
    app:barrierDirection="right"
    app:constraint_referenced_ids="flow1,flow2" />

<androidx.constraintlayout.widget.Barrier
    android:id="@+id/id_barrier2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:barrierAllowsGoneWidgets="true"
    app:barrierDirection="left"
    app:constraint_referenced_ids="flow1,flow2" />

<TextView
    android:id="@+id/text"
    android:layout_width="54dp"
    android:layout_height="46dp"
    android:background="@android:color/holo_red_dark"
    android:gravity="center"
    android:text="see"
    android:textColor="@android:color/white"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="@+id/id_barrier1"
    app:layout_constraintRight_toRightOf="@+id/id_barrier2"
    app:layout_constraintTop_toTopOf="parent" />

Guideline

android xml能修改图片颜色吗_html5_02

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_begin="60dp" />

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.5" />

<TextView
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/holo_red_dark"
    android:gravity="center"
    android:text="see"
    android:textColor="@android:color/white"
    app:layout_constraintBottom_toBottomOf="@+id/guideline1"
    app:layout_constraintLeft_toLeftOf="@+id/guideline3"
    app:layout_constraintRight_toRightOf="@+id/guideline4"
    app:layout_constraintTop_toTopOf="@+id/guideline2"
    app:layout_constraintVertical_bias="0.531" />

Chains & Weight & Bias

android xml能修改图片颜色吗_android xml能修改图片颜色吗_03

<TextView
        android:id="@+id/tab1"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintLeft_toLeftOf="@+id/guideline1"
        app:layout_constraintRight_toLeftOf="@+id/tab2" />
    <TextView
        android:id="@+id/tab2"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintLeft_toRightOf="@+id/tab1"
        app:layout_constraintRight_toLeftOf="@+id/tab3" />
    <TextView
        android:id="@+id/tab3"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintLeft_toRightOf="@+id/tab2"
        app:layout_constraintRight_toRightOf="parent" />

    <TextView
        android:id="@+id/tab4"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintLeft_toRightOf="@+id/guideline1"
        app:layout_constraintRight_toLeftOf="@+id/tab5"
        app:layout_constraintTop_toBottomOf="@+id/tab1" />
    <TextView
        android:id="@+id/tab5"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintLeft_toRightOf="@+id/tab4"
        app:layout_constraintRight_toLeftOf="@+id/tab6"
        app:layout_constraintTop_toBottomOf="@+id/tab1" />
    <TextView
        android:id="@+id/tab6"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintLeft_toRightOf="@+id/tab5"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tab1" />

    <TextView
        android:id="@+id/tab7"
        android:layout_width="0dp"
        android:layout_height="40dp"
        app:layout_constraintHorizontal_weight="3"
        app:layout_constraintLeft_toRightOf="@+id/guideline1"
        app:layout_constraintRight_toLeftOf="@+id/tab8"
        app:layout_constraintTop_toBottomOf="@+id/tab4" />
    <TextView
        android:id="@+id/tab8"
        android:layout_width="0dp"
        android:layout_height="40dp"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintLeft_toRightOf="@+id/tab7"
        app:layout_constraintRight_toLeftOf="@+id/tab9"
        app:layout_constraintTop_toBottomOf="@+id/tab4" />
    <TextView
        android:id="@+id/tab9"
        android:layout_width="0dp"
        android:layout_height="40dp"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintLeft_toRightOf="@+id/tab8"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tab4" />

    <TextView
        android:id="@+id/tab10"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintLeft_toLeftOf="@+id/guideline1"
        app:layout_constraintRight_toLeftOf="@+id/tab11"
        app:layout_constraintTop_toBottomOf="@+id/tab7" />
    <TextView
        android:id="@+id/tab11"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintLeft_toRightOf="@+id/tab10"
        app:layout_constraintRight_toLeftOf="@+id/tab12"
        app:layout_constraintTop_toBottomOf="@+id/tab7" />
    <TextView
        android:id="@+id/tab12"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintLeft_toRightOf="@+id/tab11"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tab7" />

    <TextView
        android:id="@+id/tab13"
        app:layout_constraintHorizontal_bias="0.2"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintLeft_toLeftOf="@+id/guideline1"
        app:layout_constraintRight_toLeftOf="@+id/tab14"
        app:layout_constraintTop_toBottomOf="@+id/tab10" />
    <TextView
        android:id="@+id/tab14"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintLeft_toRightOf="@+id/tab13"
        app:layout_constraintRight_toLeftOf="@+id/tab15"
        app:layout_constraintTop_toBottomOf="@+id/tab10" />
    <TextView
        android:id="@+id/tab15"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintLeft_toRightOf="@+id/tab14"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tab10" />

Group

Group帮助你对一组控件进行设置。最常见的情况是控制一组控件的visibility。你只需把控件的id添加到Group,就能同时对里面的所有控件进行操作。使用方法见下面的例子:

<android.support.constraint.Group
    android:id="@+id/group"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:constraint_referenced_ids="flow1,flow2" />

过度绘制

开发者选项(调试GPU过度绘制)

android xml能修改图片颜色吗_微信_04

常用优化手段

  • 移除 Window 默认背景:getWindow().setBackgroundDrawable(null)
  • 移除不必要的背景:如果 ViewPager 中的每个页面都设置了背景,那就可以不用给 Activity 的根布局设置背景
  • 减少透明度的使用:由于需要混色处理,至少渲染两次
  • 扁平化布局层级:使用RelativeLayout、ConstraintLayout
  • 使用优化标签:include、merge、viewstub

include 标签

常用于将布局中的公共部分提取出来供其他 layout 共用,以实现布局模块化

<?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">

    <!--测试layout和include都设置ID的情况-->
    <include
        android:id="@+id/tb_toolbar"
        layout="@layout/include_toolbar" />

    <!--如果只有单个include这样写就可以,加载的布局的子View,直接findViewByID就能找到-->
    <include layout="@layout/include_text" />

    <!--如果有多个include,需要添加ID属性-->
    <include
        android:id="@+id/include_text1"
        layout="@layout/include_text" />

    <!--如果要使用layout_margin这样的属性,要同时加上layout_w/h属性,不然没反应-->
    <include
        android:id="@+id/include_text2"
        layout="@layout/include_text_relative"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="50dp" />
    
</LinearLayout>

Activity中实例化子View:

private void initView() {
    //如果include布局根容器和include标签中的id设置的是不同的值,这里获取的mToolbar值将为null
    Toolbar mToolbar = (Toolbar) findViewById(R.id.tb_toolbar);
    setSupportActionBar(mToolbar);

    //普通include标签用法,直接拿子View属性实现
    TextView textView = (TextView) findViewById(R.id.textView);
    textView.setText("不加ID实现的include标签");

    //多个include标签用法,添加ID,findViewByID找到layout,再找子控件
    View view_include = findViewById(R.id.include_text1);
    TextView view_include_textView = (TextView) view_include.findViewById(R.id.textView);
    view_include_textView.setText("加了ID实现的include标签");

    //多个include标签用法,需要为include标签添加ID,findViewByID找到layout,再找子控件
    View view_include_Relative = findViewById(R.id.include_text2);
    TextView view_textView_relative = (TextView) view_include_Relative.findViewById(R.id.textView);
    view_textView_relative.setText("加了ID实现的include标签(RelaviteLayout)");
  }

使用 include 标签注意事项:

  • 如果 XML 布局文件有多个 include 标签,那么需要为每个 include 标签设置 ID,这样才能找到相应子 View 的控件
  • include 标签如果使用 layout_xx 属性,会覆盖待加载布局文件的根节点对应的属性
  • include 标签设置的 ID 会覆盖被 include 的 XML 文件根节点的 ID,建议设置同名的 ID,不然有可能会报空指针异常
  • 如果要在 include 标签下使用 layout_margin 等其他属性,需要同时设置 layout_width 和 layout_height,不然属性不生效

merge 标签

主要用于辅助 include 标签,该标签可以消除视图层次结构中的冗余视图

merge 标签使用场景:

  • 根布局是 FrameLayout 且不需要设置 background 或 padding 等属性,可以用 merge 代替,因为 mContentView 就是 FrameLayout
  • 建议被 include 的布局使用 merge 作为该布局的顶节点,这样在被引入时顶结点会自动被忽略
  • 自定义 View 如果继承自 ViewGroup,建议让自定义 View 的布局文件根布局设置成 merge,这样能少一层结点

使用merge标签注意事项:

  • 通过 LayoutInflate.inflate 方法渲染时,第二个参数必须指定一个父容器,且第三个参数必须为 true,也就是必须为 merge 下的视图指定一个父亲节点
  • 因为 merge 不是View,对 merge 标签设置的所有属性都是无效的
  • merge 标签必须在根布局使用
  • ViewStub 标签中的 layout 布局不能使用 merge 标签

viewstub 标签

最大的优点是当你需要时才会加载,使用它并不会影响UI初始化时的性能。各种不常用的布局像进度条、显示错误消息等可以使用 viewStub 标签,以减少内存使用量,加快渲染速度。viewStub 是一个不可见的,实际上是把宽高设置为0的 View,效果有点类似普通的 view.setVisible,但性能体验提高不少

XML标签如下:

<ViewStub
    <!--android:id:重写ViewStub的父布局控件的Id-->
    android:id="@+id/stub_import"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    <!--android:layout:设置ViewStub被inflate的布局-->
    android:inflatedId="@+id/panel_import"
    android:layout="@layout/progress_overlay" />

对应代码如下:

private void showNetError() {
    // not repeated inflate
    if (networkErrorView != null) {
      //setVisibility()方式加载布局,加载次数不限
      networkErrorView.setVisibility(View.VISIBLE);
      return;
    }
    //inflate()方式加载布局,只能加载一次
    ViewStub stub = (ViewStub) findViewById(R.id.network_error_layout);
    stub.setOnInflateListener(this);
    networkErrorView = stub.inflate();
    Button networkSetting = (Button) networkErrorView.findViewById(R.id.network_miss);
    networkSetting.setOnClickListener(this);
    Button refresh = (Button) findViewById(R.id.network_refresh);
    refresh.setOnClickListener(this);
}

ViewStub 标签注意事项:

  • ViewStub 标签不支持 merge 标签
  • ViewStub 的 inflate 只能被调用一次,第二次调用会抛出异常
  • ViewStub 标签如果设置了 android:layout_XX 属性,会覆盖待加载布局文件的根节点对应的属性