Android ConstraintLayout

一、傳統(tǒng)界面布局

在安卓開(kāi)發(fā)中,界面編程是一個(gè)很重要的部分,而很多時(shí)候?yàn)榱藢?shí)現(xiàn)好看的 ui 界面會(huì)用到很多層的布局來(lái)實(shí)現(xiàn),當(dāng)一個(gè)應(yīng)用的界面含有多個(gè)控件并且布局嵌套的層級(jí)大于三層時(shí)可能界面的渲染速度就會(huì)變慢,導(dǎo)致界面丟幀,這時(shí)界面加載起來(lái)就會(huì)很不流暢。極端情況下也會(huì)發(fā)生 ANR (Application Not Responding) 。因此一個(gè)優(yōu)秀的界面應(yīng)該盡量的去滿足以下兩點(diǎn)。

  • 布局嵌套的層級(jí)經(jīng)可能的少
  • 布局中的控件應(yīng)該盡可能的使用相對(duì)位置。
    使用相對(duì)位置可以在不用分辨率的設(shè)備中保持布局效果的一致性。

但是以上兩點(diǎn)往往是沖突的,降低嵌套層級(jí)的方式是使用 RelativeLayout, 而基于相對(duì)位置使用的是 LinearLayout。當(dāng)界面過(guò)于復(fù)雜時(shí)需要大量的 LinearLayout 保證控件的相對(duì)擺放,這樣會(huì)導(dǎo)致嵌套層級(jí)過(guò)多,如果使用 RelativeLayout控件之間的關(guān)系及其冗余,這時(shí)的界面可讀性差也難與修改。

二、ConstraintLayout布局

ConstraintLayout 即約束布局,在2016年的 Google I/O 大會(huì)上推出,可一定程度的替代掉 RelativeLayoutLinearLayout 接下來(lái)就開(kāi)始了解一些簡(jiǎn)單的用法。

  1. Hello World 的布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

這個(gè)熟悉的代碼正是新版本的 Android Studio 新建項(xiàng)目時(shí)自動(dòng)生成的布局文件,可以看到這個(gè)界面的根布局正是 ConstraintLayout。這個(gè)效果是讓 Hello World! 居中,其標(biāo)準(zhǔn)性模板如下

app:layout_constraint[ 本源位置 ]_to[ 目標(biāo)位置 ]="[ 目標(biāo)id ]"

  1. 指定約束
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/cancel_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginBottom="16dp"
        android:text="取消"
        app:layout_constraintBottom_toBottomOf="@id/constraintLayout"
        app:layout_constraintStart_toStartOf="@id/constraintLayout" />

    <Button
        android:id="@+id/next_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginBottom="16dp"
        android:text="下一步"
        app:layout_constraintBottom_toBottomOf="@id/constraintLayout"
        app:layout_constraintStart_toEndOf="@id/cancel_button" />

</android.support.constraint.ConstraintLayout>
  1. 設(shè)置比例
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="居中"
        app:layout_constraintBottom_toBottomOf="@+id/constraintLayout"
        app:layout_constraintEnd_toEndOf="@id/constraintLayout"
        app:layout_constraintStart_toStartOf="@id/constraintLayout"
        app:layout_constraintTop_toTopOf="@+id/constraintLayout" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按比例偏移"
        app:layout_constraintBottom_toBottomOf="@+id/constraintLayout"
        app:layout_constraintEnd_toEndOf="@id/constraintLayout"
        app:layout_constraintHorizontal_bias="0.25"
        app:layout_constraintStart_toStartOf="@id/constraintLayout"
        app:layout_constraintTop_toTopOf="@+id/constraintLayout"
        app:layout_constraintVertical_bias="0.25" />

</android.support.constraint.ConstraintLayout>
  1. 引導(dǎo)線布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.Guideline
        android:id="@+id/guideLine"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="72dp"
        tools:layout_editor_absoluteX="72dp"
        tools:layout_editor_absoluteY="0dp" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="向上"
        app:layout_constraintBottom_toBottomOf="@+id/constraintLayout"
        app:layout_constraintStart_toStartOf="@id/guideLine"
        app:layout_constraintTop_toTopOf="@+id/constraintLayout"
        app:layout_constraintVertical_bias="0.25"
        tools:layout_editor_absoluteX="72dp" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="向下"
        app:layout_constraintBottom_toBottomOf="@+id/constraintLayout"
        app:layout_constraintStart_toStartOf="@id/guideLine"
        app:layout_constraintTop_toTopOf="@+id/constraintLayout"
        app:layout_constraintVertical_bias="0.75"
        tools:layout_editor_absoluteX="72dp" />

</android.support.constraint.ConstraintLayout>
  1. 布局填充
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/small"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:text="自適應(yīng)大小"
        app:layout_constraintStart_toStartOf="@id/constraintLayout"
        app:layout_constraintTop_toTopOf="@id/constraintLayout" />

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="取最寬的寬度"
        app:layout_constraintBottom_toBottomOf="@id/constraintLayout"
        app:layout_constraintEnd_toEndOf="@id/constraintLayout"
        app:layout_constraintStart_toEndOf="@id/small"
        app:layout_constraintTop_toTopOf="@id/constraintLayout" />

</android.support.constraint.ConstraintLayout>
  1. 控件寬高比
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:background="@color/colorAccent"
        android:src="@mipmap/home_ban"
        app:layout_constraintDimensionRatio="16:9"
        app:layout_constraintLeft_toLeftOf="@+id/constraintLayout"
        app:layout_constraintRight_toRightOf="@+id/constraintLayout"
        app:layout_constraintTop_toTopOf="@+id/constraintLayout" />

    <ImageView
        android:layout_width="200dp"
        android:layout_height="0dp"
        android:background="@color/colorAccent"
        android:contentDescription="@null"
        android:src="@mipmap/home_ban"
        app:layout_constraintBottom_toBottomOf="@+id/constraintLayout"
        app:layout_constraintDimensionRatio="4:3"
        app:layout_constraintLeft_toLeftOf="@+id/constraintLayout"
        app:layout_constraintRight_toRightOf="@+id/constraintLayout" />

</android.support.constraint.ConstraintLayout>
  1. 圓形定位
    這個(gè)用法簡(jiǎn)直是完美的解決了消息列表里使用圓形頭像時(shí)右上角的未讀消息的點(diǎn)。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/pic"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:src="@mipmap/login_sel_rel"
        app:layout_constraintCircle="@+id/image"
        app:layout_constraintCircleAngle="45"
        app:layout_constraintCircleRadius="70dp" />

</android.support.constraint.ConstraintLayout>

參考資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。