Android ConstraintLayout約束布局簡單使用介紹

前言

什么是約束布局(ConstraintLayout)

我們可以理解為增強(qiáng)版/升級(jí)版的相對(duì)布局(RelativeLayout)。

Android Studio 從版本2.3開始創(chuàng)建xml默認(rèn)的根布局就是約束布局,相信大家對(duì)相對(duì)布局已經(jīng)是使用的非常6了客峭,所有在使用約束布局的話就會(huì)比較輕松。
那么既然已經(jīng)有相對(duì)布局了鼠锈,為什么還要用約束布局呢?最核心就是:

讓布局扁平化,減少布局嵌套的層次横缔,提高渲染效率,提升應(yīng)用性能膛锭。

所以說約束布局還是很有必要學(xué)一學(xué)的,最起碼在性能優(yōu)化方面是很有幫助的。
下面就一起開始學(xué)習(xí)吧腥光!

ConstraintLayout 官方文檔

廢話不多說,直接進(jìn)入主題艘儒。

舉個(gè)最簡單的栗子:
將一個(gè)在ConstraintLayout中居中,如下:


居中

代碼很簡單,就是給TextView添加上下左右邊界的約束即可访惜。所以寫約束布局就是寫控件的邊界約束砾嫉。

下面我們先介紹下約束屬性的寫法以及含義。

app:layout_constraintStart_toStartOf="parent"

我們來解釋下屬性:
第一個(gè)start代表的是控件自身的約束方向。
第二個(gè)start代表的目標(biāo)控件的約束方向溉旋。
第三個(gè)parent代表的是和那個(gè)控件建立約束。如果是父控件,就填parent婶溯,如果是其他控件,就填寫控件的id叙身。

下面我們就以最實(shí)用的現(xiàn)實(shí)場景來簡單學(xué)習(xí)下ConstraintLayout。

  • 控件水平排列
    代碼如下:
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    
    <TextView
        android:id="@+id/common_textview"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_margin="50dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    
    <TextView
        android:id="@+id/common_textview2"
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:layout_constraintStart_toEndOf="@+id/common_textview"
        app:layout_constraintTop_toTopOf="@+id/common_textview" />
    
    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:layout_constraintStart_toEndOf="@+id/common_textview2"
        app:layout_constraintTop_toTopOf="@+id/common_textview" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


水平排列

同理垂直方向上的排列就不多說了泣侮。

  • 垂直方向居中
    代碼如下:
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    
      <TextView
          android:id="@+id/common_textview"
          android:layout_width="100dp"
          android:layout_height="100dp"
          android:layout_margin="50dp"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <TextView
          android:id="@+id/common_textview2"
          android:layout_width="100dp"
          android:layout_height="wrap_content"
          app:layout_constraintBottom_toBottomOf="@+id/common_textview"
          app:layout_constraintStart_toEndOf="@+id/common_textview"
          app:layout_constraintTop_toTopOf="@+id/common_textview" />
     </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


垂直方向居中

重點(diǎn):讓控件自身的上邊界和先邊界分別和目標(biāo)控件的上下邊界進(jìn)行對(duì)應(yīng)約束即可漏益。

  • 垂直居中的同時(shí),高度一致
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    
      <TextView
          android:id="@+id/common_textview"
          android:layout_width="100dp"
          android:layout_height="100dp"
          android:layout_margin="50dp"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <TextView
          android:id="@+id/common_textview2"
          android:layout_width="100dp"
          android:layout_height="0dp"
          android:layout_marginStart="70dp"
          app:layout_constraintBottom_toBottomOf="@+id/common_textview"
          app:layout_constraintStart_toEndOf="@+id/common_textview"
          app:layout_constraintTop_toTopOf="@+id/common_textview" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


垂直居中且高度相等

其實(shí)很簡單权埠,只需要將控件自身的高度設(shè)置為0dp即可,0dp的意思就是match constraint满俗,就是充滿約束。

  • 基于某個(gè)控件的下邊界線居中
    代碼如下:
     <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    
      <TextView
          android:background="#FFD115"
          android:id="@+id/common_textview"
          android:layout_width="match_parent"
          android:layout_height="100dp"
          android:layout_margin="50dp"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <TextView
          app:layout_constraintStart_toStartOf="@id/common_textview"
          app:layout_constraintEnd_toEndOf="@id/common_textview"
          app:layout_constraintTop_toBottomOf="@id/common_textview"
          app:layout_constraintBottom_toBottomOf="@id/common_textview"
          android:background="@color/color_FFD115"
          android:id="@+id/common_textview2"
          android:layout_width="60dp"
          android:layout_height="50dp" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


邊界居中

重點(diǎn):控件自身的垂直約束方向都和目標(biāo)控件的底邊建立約束即可沉删。

  • 權(quán)重平分空間
    寬度相同砖茸,平分間距。
    代碼如下:
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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">
    
      <View
          android:id="@+id/common_view"
          android:layout_width="100dp"
          android:layout_height="100dp"
          app:layout_constraintEnd_toStartOf="@id/common_view2"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <View
          android:id="@+id/common_view2"
          android:layout_width="100dp"
          android:layout_height="100dp"
          app:layout_constraintEnd_toStartOf="@id/common_view3"
          app:layout_constraintStart_toEndOf="@id/common_view"
          app:layout_constraintTop_toTopOf="parent" />
    
      <View
          android:id="@+id/common_view3"
          android:layout_width="100dp"
          android:layout_height="100dp"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintStart_toEndOf="@id/common_view2"
          app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


同等寬度間距平分

控件寬度平分,只需要改變上述代碼中的android:layout_width="0dp"即可實(shí)現(xiàn)。
代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

   <View
       android:id="@+id/common_view"
       android:layout_width="0dp"
       android:layout_height="100dp"
       app:layout_constraintEnd_toStartOf="@id/common_view2"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />

   <View
       android:id="@+id/common_view2"
       android:layout_width="0dp"
       android:layout_height="100dp"
       app:layout_constraintEnd_toStartOf="@id/common_view3"
       app:layout_constraintStart_toEndOf="@id/common_view"
       app:layout_constraintTop_toTopOf="parent" />

   <View
       android:id="@+id/common_view3"
       android:layout_width="0dp"
       android:layout_height="100dp"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toEndOf="@id/common_view2"
       app:layout_constraintTop_toTopOf="parent" />


</androidx.constraintlayout.widget.ConstraintLayout>

效果圖如下:


平分空間

重點(diǎn):讓寬度為0dp,充滿約束即可拐邪。

根據(jù)不同的權(quán)重實(shí)現(xiàn)不同比例的平分,這里的權(quán)重的使用必須是充滿約束才會(huì)生效,即寬度為0dp惰赋,而且約束布局的權(quán)重分為垂直和水平兩個(gè)方向。
代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

  <View
      android:id="@+id/common_view"
      android:layout_width="0dp"
      android:layout_height="100dp"
      app:layout_constraintHorizontal_weight="3"
      app:layout_constraintEnd_toStartOf="@id/common_view2"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent" />

  <View
      app:layout_constraintHorizontal_weight="2"
      android:id="@+id/common_view2"
      android:layout_width="0dp"
      android:layout_height="100dp"
      app:layout_constraintEnd_toStartOf="@id/common_view3"
      app:layout_constraintStart_toEndOf="@id/common_view"
      app:layout_constraintTop_toTopOf="parent" />

  <View
      app:layout_constraintHorizontal_weight="1"
      android:id="@+id/common_view3"
      android:layout_width="0dp"
      android:layout_height="100dp"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toEndOf="@id/common_view2"
      app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

效果圖如下:


權(quán)重平分

這里只寫了水平方向上的權(quán)重挨务,垂直方向上的權(quán)重同理果漾。

  • 不同大小文字的對(duì)齊(基準(zhǔn)線對(duì)齊)
    代碼如下:
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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">
    
      <TextView
          android:id="@+id/view1"
          app:layout_constraintTop_toTopOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          android:text="78"
          android:textSize="128sp"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>
    
      <TextView
          app:layout_constraintStart_toEndOf="@+id/view1"
          app:layout_constraintBaseline_toBaselineOf="@+id/view1"
          android:text="%"
          android:textSize="40sp"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>
    
      <TextView
          android:id="@+id/view2"
          android:layout_marginTop="260dp"
          app:layout_constraintTop_toTopOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          android:text="78"
          android:textSize="128sp"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>
    
      <TextView
          app:layout_constraintStart_toEndOf="@+id/view2"
          app:layout_constraintBottom_toBottomOf="@+id/view2"
          android:text="%"
          android:textSize="40sp"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>
    
     </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


文字基準(zhǔn)線對(duì)齊
  • 角度定位
    使用角度定位需要3個(gè)條件:1.圓心 2.半徑 3.角度户辱。其中角度是從正上方順時(shí)針開始的。
    代碼如下:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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">
    
      <ImageView
          android:id="@+id/view_sun"
          android:layout_width="80dp"
          android:layout_height="80dp"
          android:src="@drawable/sun"
          app:layout_constraintBottom_toBottomOf="parent"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <ImageView
          android:id="@+id/view_earth"
          android:layout_width="40dp"
          android:layout_height="40dp"
          android:src="@drawable/earth"
          app:layout_constraintCircle="@+id/view_sun"
          app:layout_constraintCircleAngle="45"
          app:layout_constraintCircleRadius="150dp" />
    
      <ImageView
          android:id="@+id/view_moon"
          android:layout_width="20dp"
          android:layout_height="20dp"
          android:src="@drawable/moon"
          app:layout_constraintCircle="@+id/view_earth"
          app:layout_constraintCircleAngle="130"
          app:layout_constraintCircleRadius="30dp" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    說明:

    layout_constraintCircle 以哪個(gè)view為圓心
    layout_constraintCircleRadius 圓的半徑
    layout_constraintCircleAngle 旋轉(zhuǎn)角度, 以第一象限順時(shí)針開始粟矿。

    效果如下:


    角度定位
  • 約束寬度
    一個(gè)文本的長度不能超過圖片的寬度。
    代碼如下:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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:background="@android:color/black"
      android:layout_height="match_parent">
    
      <ImageView
          android:src="@drawable/sun"
          android:scaleType="fitXY"
          android:id="@+id/view1"
          android:layout_width="260dp"
          android:layout_height="80dp"
          android:layout_marginTop="50dp"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <TextView
          android:layout_marginTop="10dp"
          android:textColor="@android:color/white"
          app:layout_constrainedWidth="true"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:gravity="center"
          android:text="文本很長很長文本很長很長文本很長很長文本很長很長文本很長很長文本很長很長"
          android:textSize="12sp"
          app:layout_constraintEnd_toEndOf="@+id/view1"
          app:layout_constraintStart_toStartOf="@+id/view1"
          app:layout_constraintTop_toBottomOf="@+id/view1" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


約束寬度

可以看到文本的整體的寬度被約束為和上面的圖片等寬荆姆,高度的約束也是同理蒙幻。

  • bias,約束傾向胞枕,取值范圍:0.0-1.0杆煞。 0.0最左側(cè)魏宽,1.0最右側(cè)。一般配合約束寬度來使用队询。
    看下聊天的UI效果如下:


    聊天

    文字短的時(shí)候包裹內(nèi)容派桩,超過最大寬度換行展示。
    代碼如下:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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"
      android:background="@android:color/black">
    
      <ImageView
          android:id="@+id/view1"
          android:layout_width="40dp"
          android:layout_height="40dp"
          android:layout_marginTop="50dp"
          android:scaleType="fitXY"
          android:layout_marginStart="15dp"
          android:src="@drawable/sun"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <TextView
          android:paddingTop="3dp"
          android:paddingBottom="3dp"
          android:paddingStart="2dp"
          android:paddingEnd="2dp"
          android:background="@android:color/holo_red_dark"
          android:layout_marginEnd="15dp"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintHorizontal_bias="0"
          app:layout_constrainedWidth="true"
          app:layout_constraintStart_toEndOf="@+id/view1"
          app:layout_constraintTop_toTopOf="@+id/view1"
          android:layout_marginStart="8dp"
          android:text="君不見蚌斩,黃河之水天上來铆惑,奔流到海不復(fù)回。君不見送膳,高堂明鏡悲白發(fā)员魏,朝如青絲暮成雪。人生得意須盡歡叠聋,莫使金樽空對(duì)月撕阎。"
          android:textColor="@android:color/white"
          android:textSize="16sp" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:

  1. 短文字效果


    短文字長度效果
  2. 中等文字效果


    中等文字長度效果
  3. 超長文字效果


    超長文字長度效果

    水平方向上的約束傾向如上,垂直方向上的約束傾向同理碌补。

  • GoneMargin虏束。當(dāng)約束目標(biāo)控件隱藏時(shí),控件自身可以保留一定的間距厦章。
    代碼如下:
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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"
      android:background="@android:color/black">
    
      <ImageView
          android:visibility="gone"
          android:id="@+id/view1"
          android:layout_width="40dp"
          android:layout_height="40dp"
          android:layout_marginTop="50dp"
          android:scaleType="fitXY"
          android:layout_marginStart="15dp"
          android:src="@drawable/sun"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <TextView
          app:layout_goneMarginStart="30dp"
          android:paddingTop="3dp"
          android:paddingBottom="3dp"
          android:paddingStart="2dp"
          android:paddingEnd="2dp"
          android:background="@android:color/holo_red_dark"
          android:layout_marginEnd="15dp"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintHorizontal_bias="0"
          app:layout_constrainedWidth="true"
          app:layout_constraintStart_toEndOf="@+id/view1"
          app:layout_constraintTop_toTopOf="@+id/view1"
          android:layout_marginStart="8dp"
          android:text="君不見镇匀,黃河之水天上來,奔流到海不復(fù)回袜啃。君不見汗侵,高堂明鏡悲白發(fā),朝如青絲暮成雪。人生得意須盡歡晰韵,莫使金樽空對(duì)月冀值。"
          android:textColor="@android:color/white"
          android:textSize="16sp" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:

  1. 正常情況


    GoneMargin1
  2. 當(dāng)約束控件隱藏,但是不加GoneMargin屬性宫屠。
    GoneMargin2
  3. 當(dāng)約束控件隱藏列疗,加上GoneMargin屬性。
    GoneMargin3

    可以看出來GoneMargin的作用了吧浪蹂。
  • 約束鏈風(fēng)格 ChainStyle
    風(fēng)格:packed(打包抵栈,組合),spread(擴(kuò)散坤次,默認(rèn))古劲,spread_inside(內(nèi)部擴(kuò)散)。而且約束鏈風(fēng)格必須寫在第一個(gè)控件上才有效缰猴。

    1. 組件組合后居中
      代碼如下:
      <?xml version="1.0" encoding="utf-8"?>
      <androidx.constraintlayout.widget.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"
        android:background="@android:color/black">
      
        <ImageView
            android:id="@+id/view1"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:scaleType="fitXY"
            android:src="@drawable/sun"
            app:layout_constraintVertical_chainStyle="packed"
            app:layout_constraintBottom_toTopOf="@+id/view2"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
      
        <TextView
            android:id="@+id/view2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/holo_red_dark"
            android:paddingStart="2dp"
            android:paddingTop="3dp"
            android:paddingEnd="2dp"
            android:paddingBottom="3dp"
            android:text="君不見产艾,黃河之水天上來,奔流到海不復(fù)回滑绒。"
            android:textColor="@android:color/white"
            android:textSize="16sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/view1" />
      
      </androidx.constraintlayout.widget.ConstraintLayout>
      

      效果如下:


      垂直方向約束鏈風(fēng)格

      而且還支持約束傾向bias.水平方向同理闷堡。

      1. 組件內(nèi)部擴(kuò)散
        代碼如下:
       <?xml version="1.0" encoding="utf-8"?>
      <androidx.constraintlayout.widget.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"
        android:background="@android:color/black">
      
        <View
            app:layout_constraintHorizontal_chainStyle="spread_inside"
            android:id="@+id/view1"
            android:layout_width="100dp"
            android:layout_height="200dp"
            android:background="@android:color/holo_red_dark"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/view2"
            app:layout_constraintStart_toStartOf="parent" />
      
        <View
            android:id="@+id/view2"
            android:layout_width="100dp"
            android:layout_height="200dp"
            android:background="@android:color/holo_red_dark"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/view3"
            app:layout_constraintStart_toEndOf="@+id/view1" />
      
        <View
            android:id="@+id/view3"
            android:layout_width="100dp"
            android:layout_height="200dp"
            android:background="@android:color/holo_red_dark"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/view2" />
      
      </androidx.constraintlayout.widget.ConstraintLayout>
      

      效果如下:


      spread_inside

      垂直方向同理。

  • 控件寬高比例保持一致疑故, DimensionRatio
    使用這個(gè)屬性的前提是杠览,控件的寬或者高至少有一個(gè)是充滿約束的,即為0dp纵势。
    代碼如下:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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"
      android:background="@android:color/black">
    
      <ImageView
          android:id="@+id/view1"
          android:layout_width="200dp"
          android:layout_height="0dp"
          app:layout_constraintDimensionRatio="2:1"
          android:background="@drawable/sun"
          app:layout_constraintBottom_toBottomOf="parent"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

寬高比:2:1
效果如下:


DimensionRatio

如果寬和高都是0dp踱阿,DimensionRatio需要加上“H,2:1”,這個(gè)H說明高度是計(jì)算出來的钦铁,也就是說寬度充滿約束软舌,這里就不再演示了。

  • 百分比布局牛曹,寬度或者高度占parent的百分比
    這個(gè)百分比始終是針對(duì)parent的百分比佛点,而且使用百分比的前提是寬度或者高度必須充滿約束,即0dp躏仇。
    代碼如下:
     <?xml version="1.0" encoding="utf-8"?>
     <androidx.constraintlayout.widget.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"
      android:background="@android:color/black">
    
      <View
          android:background="@android:color/holo_red_dark"
          android:layout_width="0dp"
          app:layout_constraintTop_toTopOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintWidth_percent="0.3"
          android:layout_height="320dp"/>
    
      <View
          android:background="@android:color/holo_green_dark"
          android:layout_width="0dp"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintTop_toTopOf="parent"
          app:layout_constraintWidth_percent="0.5"
          android:layout_height="320dp"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


百分比

第一個(gè)View 寬度占parent 的30%恋脚, 第二個(gè)View寬度占parent的50%,垂直方向上的百分比同理焰手。

  • GuideLine(基準(zhǔn)線/輔助線)
    這個(gè)是輔助控件糟描,輔助控件之間的約束,而不是一個(gè)真正的控件书妻。
    下面舉一個(gè)簡單的UI栗子船响,比如登錄頁面躬拢。
    代碼如下:
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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"
      android:background="@android:color/black">
    
      <androidx.constraintlayout.widget.Guideline
          android:id="@+id/guide_line"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:orientation="vertical"
          app:layout_constraintGuide_percent="0.2" />
    
      <TextView
          android:id="@+id/tv_username"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginTop="70dp"
          android:paddingTop="20dp"
          android:paddingBottom="20dp"
          android:text="用戶名"
          android:textColor="@android:color/white"
          android:textSize="16sp"
          app:layout_constraintEnd_toStartOf="@+id/guide_line"
          app:layout_constraintTop_toTopOf="parent" />
    
      <EditText
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginStart="8dp"
          android:background="@android:color/white"
          android:hint="輸入用戶名"
          android:textColorHint="@android:color/black"
          app:layout_constraintBaseline_toBaselineOf="@id/tv_username"
          app:layout_constraintStart_toEndOf="@+id/guide_line" />
    
      <TextView
          android:id="@+id/tv_password"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:paddingTop="20dp"
          android:paddingBottom="20dp"
          android:text="密碼"
          android:textColor="@android:color/white"
          android:textSize="16sp"
          app:layout_constraintEnd_toStartOf="@+id/guide_line"
          app:layout_constraintTop_toBottomOf="@+id/tv_username" />
    
      <EditText
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginStart="8dp"
          android:background="@android:color/white"
          android:hint="輸入密碼"
          android:textColor="@android:color/black"
          android:textColorHint="@android:color/black"
          app:layout_constraintBaseline_toBaselineOf="@+id/tv_password"
          app:layout_constraintStart_toEndOf="@+id/guide_line" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


GuidLine
  • Group
    當(dāng)某一種狀態(tài)下需要多好多控件進(jìn)行隱藏和顯示時(shí),可以使用Group见间,來統(tǒng)一顯示和隱藏聊闯。
    代碼如下:
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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"
      android:background="@android:color/black">
    
      <androidx.constraintlayout.widget.Group
          android:id="@+id/group1"
          android:layout_width="wrap_content"
          android:visibility="gone"
          android:layout_height="wrap_content"
          app:constraint_referenced_ids="tv1,tv2" />
    
      <androidx.constraintlayout.widget.Group
          android:id="@+id/group2"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          app:constraint_referenced_ids="tv3,tv4" />
    
      <TextView
          android:id="@+id/tv1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginTop="10dp"
          android:padding="15dp"
          android:text="group1"
          android:textColor="@android:color/white"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <TextView
          android:id="@+id/tv2"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:padding="15dp"
          android:text="group1-2"
          android:textColor="@android:color/white"
          app:layout_constraintStart_toEndOf="@+id/tv1"
          app:layout_constraintTop_toTopOf="@+id/tv1" />
    
      <TextView
          android:id="@+id/tv3"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginStart="30dp"
          android:layout_marginTop="80dp"
          android:padding="15dp"
          android:text="group2"
          android:textColor="@android:color/white"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <TextView
          android:id="@+id/tv4"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:padding="15dp"
          android:text="group2-1"
          android:textColor="@android:color/white"
          app:layout_constraintStart_toEndOf="@+id/tv3"
          app:layout_constraintTop_toTopOf="@+id/tv3" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:
設(shè)置Group1的visibility=visible時(shí),效果如下:


Visible

設(shè)置Group1的visibility=gone時(shí)米诉,效果如下:


Gone
  • Layer
    也是一個(gè)約束輔助菱蔬,它的使用和Group類似,只不過layer可以對(duì)整體進(jìn)行旋轉(zhuǎn)史侣,平移等常用的操作拴泌。
    代碼如下:
    public class CommonTest extends FragmentActivity {
    
      @Override
      protected void onCreate(@Nullable Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.common_constraint_layout_demo);
          findViewById(R.id.layer).setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  //旋轉(zhuǎn)45d°
                  findViewById(R.id.layer).setRotation(45);
                  //X軸向右平移100px
                  findViewById(R.id.layer).setTranslationX(100);
                  //Y軸向下平移100px
                  findViewById(R.id.layer).setTranslationY(100);
              }
          });
      }
    }
    
    
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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"
      android:background="@android:color/black">
    
      <Button
          android:id="@+id/button"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginStart="5dp"
          android:layout_marginTop="10dp"
          android:text="旋轉(zhuǎn)"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <androidx.constraintlayout.helper.widget.Layer
          android:id="@+id/layer"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          app:constraint_referenced_ids="tv1,tv2,tv3,tv4"
          tools:ignore="MissingConstraints" />
    
      <TextView
          android:id="@+id/tv1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginStart="15dp"
          android:layout_marginTop="10dp"
          android:background="@android:color/holo_blue_light"
          android:padding="10dp"
          android:text="text1"
          android:textColor="@android:color/white"
          android:textSize="16sp"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toBottomOf="@+id/button" />
    
      <TextView
          android:id="@+id/tv2"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:background="@android:color/holo_green_dark"
          android:padding="10dp"
          android:text="text2"
          android:textColor="@android:color/white"
          android:textSize="16sp"
          app:layout_constraintStart_toEndOf="@+id/tv1"
          app:layout_constraintTop_toTopOf="@+id/tv1" />
    
      <TextView
          android:id="@+id/tv3"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginStart="30dp"
          android:layout_marginTop="40dp"
          android:background="@android:color/darker_gray"
          android:padding="10dp"
          android:text="text3"
          android:textColor="@android:color/white"
          android:textSize="16sp"
          app:layout_constraintStart_toStartOf="@+id/tv1"
          app:layout_constraintTop_toBottomOf="@+id/tv1" />
    
      <TextView
          android:id="@+id/tv4"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:background="@android:color/holo_purple"
          android:padding="10dp"
          android:text="text4"
          android:textColor="@android:color/white"
          android:textSize="16sp"
          app:layout_constraintStart_toEndOf="@+id/tv3"
          app:layout_constraintTop_toTopOf="@+id/tv3" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


Layer
  • Barrier
    屏障,柵欄。給約束控件設(shè)置約束上的屏障惊橱,已達(dá)到約束位置的目的蚪腐。
    代碼如下:
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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"
      android:background="@android:color/black"
      tools:context=".ui.CommonTest">
    
      <androidx.constraintlayout.widget.Barrier
          android:id="@+id/barrier"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          app:barrierDirection="end"
          app:constraint_referenced_ids="tv1,tv2"
          tools:ignore="MissingConstraints" />
    
      <TextView
          android:id="@+id/tv1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginTop="15dp"
          android:text="文本1文本1文本1文本1文本1"
          android:textColor="@android:color/white"
          android:textSize="15sp"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <TextView
          android:id="@+id/tv2"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginTop="30dp"
          android:text="文本2文本2"
          android:textColor="@android:color/white"
          android:textSize="15sp"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toBottomOf="@+id/tv1" />
    
      <ImageView
          android:id="@+id/iv1"
          android:layout_width="25dp"
          android:layout_height="25dp"
          android:src="@drawable/moon"
          app:layout_constraintStart_toEndOf="@+id/barrier"
          app:layout_constraintTop_toTopOf="@+id/tv1" />
    
      <ImageView
          android:id="@+id/iv2"
          android:layout_width="25dp"
          android:layout_height="25dp"
          android:src="@drawable/moon"
          app:layout_constraintStart_toEndOf="@+id/barrier"
          app:layout_constraintTop_toTopOf="@+id/tv2" />
    
     </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


Barrier

像:Group,Layer税朴,Barrier都是以ID的引用來實(shí)現(xiàn)的回季,所以如果使用了特殊的混淆工具,對(duì)id資源進(jìn)行了混淆正林,這里就需要注意下泡一,不然運(yùn)行起來會(huì)找不到id的。

  • Placeholder
    占位符卓囚。
    代碼如下:
     public class CommonTest extends FragmentActivity {
    
      @Override
      protected void onCreate(@Nullable Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.common_constraint_layout_demo);
      }
    
      public void onClick(View view) {
          findViewById(R.id.placeholder).setContentId(view.getId());
      }
    }
    
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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"
      android:background="@android:color/black"
      tools:context=".ui.CommonTest">
    
      <androidx.constraintlayout.widget.Placeholder
          android:id="@+id/placeholder"
          android:layout_width="50dp"
          android:layout_height="50dp"
          android:layout_marginTop="20dp"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
      <ImageView
          android:id="@+id/iv1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:src="@drawable/sun"
          app:layout_constraintBottom_toBottomOf="parent"
          app:layout_constraintEnd_toStartOf="@+id/iv2"
          app:layout_constraintStart_toStartOf="parent" />
    
      <ImageView
          android:id="@+id/iv2"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:src="@drawable/earth"
          app:layout_constraintEnd_toStartOf="@+id/iv3"
          app:layout_constraintStart_toEndOf="@+id/iv1"
          app:layout_constraintTop_toTopOf="@+id/iv1" />
    
      <ImageView
          android:id="@+id/iv3"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:src="@drawable/moon"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintStart_toEndOf="@+id/iv2"
          app:layout_constraintTop_toTopOf="@+id/iv1" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

效果如下:


Placeholder

當(dāng)點(diǎn)擊下面3個(gè)view其中一個(gè)view的時(shí)候瘾杭,被點(diǎn)擊的view會(huì)被替換到上面的Placeholder所在的位置。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哪亿,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子贤笆,更是在濱河造成了極大的恐慌蝇棉,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芥永,死亡現(xiàn)場離奇詭異篡殷,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)埋涧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門板辽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人棘催,你說我怎么就攤上這事劲弦。” “怎么了醇坝?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵邑跪,是天一觀的道長。 經(jīng)常有香客問我,道長画畅,這世上最難降的妖魔是什么砸琅? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮轴踱,結(jié)果婚禮上症脂,老公的妹妹穿的比我還像新娘。我一直安慰自己淫僻,他們只是感情好摊腋,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嘁傀,像睡著了一般兴蒸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上细办,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天橙凳,我揣著相機(jī)與錄音,去河邊找鬼笑撞。 笑死岛啸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的茴肥。 我是一名探鬼主播坚踩,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瓤狐!你這毒婦竟也來了瞬铸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤础锐,失蹤者是張志新(化名)和其女友劉穎嗓节,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體皆警,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拦宣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了信姓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鸵隧。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖意推,靈堂內(nèi)的尸體忽然破棺而出豆瘫,到底是詐尸還是另有隱情,我是刑警寧澤左痢,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布靡羡,位于F島的核電站系洛,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏略步。R本人自食惡果不足惜描扯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望趟薄。 院中可真熱鬧绽诚,春花似錦、人聲如沸杭煎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽羡铲。三九已至蜂桶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間也切,已是汗流浹背扑媚。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留雷恃,地道東北人疆股。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像倒槐,于是被迫代替她去往敵國和親旬痹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容