1. 程式人生 > >ConstraintLayout屬性介紹及使用

ConstraintLayout屬性介紹及使用

ConstraintLayout屬性介紹及使用

文章目錄


相信大家對ConstraintLayout並不陌生,Android Studio升級2.2之後,預設生成的XML佈局已經從原來的RelativeLayout替換為ConstraintLayout,並且goole在去年的I/O大會上重點推出介紹了這個控制元件,對於ConstraintLayout到目前為止已經推出了很多的使用方法和屬性還是比較給力的,並且到目前為止Google還在繼續豐富其API和功能,所以這對於開發者而言是一個大的福音!下面我們就來看看它到底高明在哪裡!!!

說明:因為文章中會用到大部分的ConstraintLayout的名詞,我們在文章中會使用CL縮寫來代替,使用RL代替RelativeLayout。

要引入ConstraintLayout的使用,我們需要在gradle檔案中新增

implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta3'

Relative positioning(相對位置)

循序漸進,我們從最基本的來,這是我使用ConstraintLayout寫的一個佈局效果:

在這裡插入圖片描述

這樣的佈局是我們平時很常見的效果,下面我們就看看使用ConstraintLayout時如何實現的:

<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="com.example.ljj.constraintlayoutdemo.demolist.RelativePositioningActivity">
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:title="相對位置"
        app:titleTextColor="@android:color/white" />

    <TextView
        android:id="@+id/text_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/fab_margin"
        android:layout_marginTop="@dimen/fab_margin"
        android:text="奚夢瑤維密秀摔倒道歉"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar" />

    <ImageView
        android:id="@+id/image"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:layout_marginTop="10dp"
        android:scaleType="fitXY"
        android:src="@drawable/image"
        app:layout_constraintLeft_toLeftOf="@id/text_title"
        app:layout_constraintTop_toBottomOf="@+id/text_title" />

    <TextView
        android:id="@+id/text_content"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="@dimen/fab_margin"
        android:text="11月20日晚,一眾國內外維密天使閃亮登場。但在表演環節中,奚夢瑤不慎出現意外跌倒在臺上,意外發生後,奚夢瑤立刻整理了一下頭髮和身上的裝飾,站起身來繼續走T臺,並且露出專業和自信的笑容,全場觀眾也為她拍手鼓勵。"
        app:layout_constraintLeft_toRightOf="@+id/image"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@+id/image" />


    <TextView
        android:id="@+id/text_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="時間:2小時前"
        app:layout_constraintLeft_toLeftOf="@id/image"
        app:layout_constraintTop_toBottomOf="@+id/image" />
</android.support.constraint.ConstraintLayout>

從上面程式碼中可以發現,我們可以看到一共四個控制元件元素,在text_title中有兩個屬性:

app:layout_constraintLeft_toLeftOf="parent"

不難理解,此屬性的意思是text_title元素的左側和父佈局的左側對齊,這是和父佈局設定的相對依賴關係

app:layout_constraintTop_toBottomOf="@+id/toolbar"

此屬性的意思是text_title的頂部在toolbar控制元件的下方,這是text_title設定的和toolbar位置上的依賴關係,如果我們希望控制元件A在控制元件B的下面,就可以這麼寫。

繼續往下看text_content中還設定了

app:layout_constraintTop_toTopOf="@+id/image"

此屬性的作用是使text_content和image空間頂部對齊,相當於RL中的marginTop。

這些屬性的使用並不難理解,和RL中除了寫法不同,理解起來都差不多,但是寫的過程中,我發現了一些細節:
1、說明,如果直接設定marginLeft是不起作用的,需要和layout_constraintLeft_toLeftOf等對應的屬性搭配使用
2、我們將text_content的 android:layout_width=”0dp”設定為0dp,這就跟RL的寫法不同了,稍後介紹這個屬性,下面先看小CL提供的相對位置依賴的屬性:其中大部分在上面的例子中已經涉及到了,也不難理解,大家可以自己試下。

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_constraintBaseline_toBaselineOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf

MATCH_CONSTRAINT

我們在上面留了一個問題,就是

android:layout_width="0dp"

將寬度設定為0dp在CL中意味著什麼呢?
現將android:layout_width修改為wrap_content試試,效果如下:

在這裡插入圖片描述

可以看到text_content的內容已經脫離了之前的依賴,對於解決這種問題,我們就可以使用0dp的設定,那這個0dp又以為只什麼呢?官方是這樣介紹的:

Using 0dp, which is the equivalent of "MATCH_CONSTRAINT"
Important: MATCH_PARENT is not recommended for widgets contained in a 
ConstraintLayout. Similar behavior can be defined by using MATCH_CONSTRAINT
 with the corresponding left/right or top/bottom constraints being
  set to "parent".

也就是說在CL中MATCH_PARENT已經不存在了,對於這個屬性值,我們就介紹到這裡,至於為什麼要這樣改,我也不知道CL是怎麼想的

Centering positioning And Bias (居中和偏移量)

上程式碼:

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    ....
    ">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        ... />

    <Button
        android:id="@+id/button_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/fab_margin"
        android:text="居中"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <Button
        android:id="@+id/button_bias"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/fab_margin"
        android:text="偏移量"
        app:layout_constraintHorizontal_bias="0.1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button_center" />

</android.support.constraint.ConstraintLayout>

對應實現效果:
在這裡插入圖片描述

先看居中的button_center 元素設定了兩個屬性:

app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

設定這兩個屬性之後說明父佈局的左右拉力對button是相等的,所以button居中,使用CL寫XML時,左右居中使用上面兩個屬性,相對應的上下居中使用屬性:

app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"

再看button_bias的屬性中多了一個

app:layout_constraintHorizontal_bias="0.1"

此屬性就是設定水平方向的偏移量,0.1表示左右側距離比為1:9,此屬性必須和居中屬性一起顯示才會起作用,相對應的還有

layout_constraintVertical_bias 

Circular positioning(圓形定位)

看到這個功能時我是激動的,瞬間覺得CL提升了一個檔次,圓形定位的相關屬性是在CL1.1版本新增的功能,個人感覺很好用,然後就路轉粉了,哈哈,我先貼出一張圖:

在這裡插入圖片描述

相信大家對這個型別的佈局都不陌生,無論是專案中增加新功能,還是IM聊天中有新訊息,都會有類似的需求,下面來瞅瞅CL是如何實現的

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    ...>

    <ImageView
        android:id="@+id/image"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/icon_circle"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/image_point"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/red_point"
        app:layout_constraintCircle="@id/image"
        app:layout_constraintCircleAngle="35"
        app:layout_constraintCircleRadius="40dp" />

</android.support.constraint.ConstraintLayout>

從XML中可以看出image_point也就是上面的原點提示中有三個屬性:

app:layout_constraintCircle="@id/image"   //表示以image為原點
app:layout_constraintCircleAngle="35"     //與數值角度為35的方向上佈局此控制元件
app:layout_constraintCircleRadius="40dp"  //半徑40

對這三個屬性,官方給了一張圖非常清楚的表達了這三個引數的含義:

在這裡插入圖片描述

提示:此屬性是CL在1.1版本新增的,如果要使用,請把你的CL升級為1.1

Margins

對於margins,CL也提出了一些屬性,如下:

android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom

但是因為這些屬性和RL中的意義和使用方式都相同,所以這裡不做過多的介紹,重點介紹下我們之前沒有的

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom

這幾個屬性和上面的不同之處在於前面多了一個gone,什麼意思呢,上圖來說話:

在這裡插入圖片描述

這是使用CL寫的依賴佈局:底部文字依賴於圖片,在圖片的下方,如果我將上面的圖隱藏掉,會這樣子

在這裡插入圖片描述

但是怎麼辦,我的需求是即使將圖片隱藏掉,我底部的文字位置不變,這是這個新的屬性就可以起作用了,在下面的文字上設定

app:layout_goneMarginTop="100dp" 

ok啦,你儘管去GONE,我才不怕:
在這裡插入圖片描述

注:當text的位置依賴的元素GONE之後,此屬性才會起作用

ratio (寬高比)

關於設定ratio的屬性如下:

app:layout_constraintDimensionRatio="2:1" 
app:layout_constraintDimensionRatio="H,2:1"
app:layout_constraintDimensionRatio="w,2:1"
<TextView
   android:layout_width="0dp"
   android:layout_height="0dp"
   android:background="@color/colorAccent"
   app:layout_constraintDimensionRatio="2:1"
   app:layout_constraintLeft_toLeftOf="parent"
   app:layout_constraintRight_toRightOf="parent"
   />

在XML中,設定了app:layout_constraintDimensionRatio=”2:1”方法,對於這個控制元件來說,其寬高比為2:1,如圖
在這裡插入圖片描述

我們在設定ratio時,將寬高都設定為match_constraint,就是0dp,並且添加了如下屬性才會起作用:

app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

除此之外,還有兩個屬性:

app:layout_constraintDimensionRatio="H,2:1"
app:layout_constraintDimensionRatio="w,2:1"

可以自己試一下,在水平和豎直方向設定時對應的不同效果。

Chains(鏈條)

今天很累,寫到這裡已經語無倫次的趕腳,快刀斬亂麻,直接上圖:

在這裡插入圖片描述

看到官網介紹,將chains相關的屬性和使用情況都試了一遍,大致就是這樣紙滴,對這些形狀分別介紹寫法:

1、三個控制元件等分,類似於專案底部tab實現
在這裡插入圖片描述


    <Button
        android:id="@+id/button1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="亂花"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/button2" />

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="漸欲"
        app:layout_constraintLeft_toRightOf="@id/button1"
        app:layout_constraintRight_toLeftOf="@id/button3" />

    <Button
        android:id="@+id/button3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="迷人眼"
        app:layout_constraintLeft_toRightOf="@id/button2"
        app:layout_constraintRight_toRightOf="parent" />

為每個元素新增兩兩相互依賴,來實現等分功能,在這裡我們還可以通過

app:layout_constraintHorizontal_weight

來控制每個元素的Item,這裡的weight使用和LL中的使用方式一致,如果我將他們的weight設定分別為1,1,2,則效果為:

在這裡插入圖片描述

注:實現橫向等分功能,必須設定寬度為0dp,並且兩兩互相依賴。

2、效果2,下面兩張圖是效果實現和官網上對這種效果的chains(鏈)作用力
在這裡插入圖片描述

在這裡插入圖片描述

可以看到A為head,在head元素中設定其chainStyle可以改變對鏈條之前的相互作用力,來實現不同效果

 <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/margin_top"
        android:text="淺草"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/button5"
        app:layout_constraintTop_toBottomOf="@id/button1" />

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="才能"
        app:layout_constraintLeft_toRightOf="@id/button4"
        app:layout_constraintRight_toLeftOf="@id/button6"
        app:layout_constraintTop_toTopOf="@id/button4"

        />

    <Button
        android:id="@+id/button6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="沒馬蹄"
        app:layout_constraintLeft_toRightOf="@id/button5"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@id/button4" />
app:layout_constraintHorizontal_chainStyle="spread"
android:layout_width="wrap_content"

這兩個屬性組合實現上述效果,注,chainStyle的預設值是spread,如果不設定chainStyle的屬性,則預設為spread

3、效果三

實現:

app:layout_constraintHorizontal_chainStyle=“spread_inside”
android:layout_width=“wrap_content”
1
2
4、效果四
在這裡插入圖片描述

實現:

app:layout_constraintHorizontal_chainStyle="packed"
android:layout_width="wrap_content"

除此之外,效果4還可以和我們上面介紹的Bias(偏移量一起使用),實現偏移效果。

總結:所以app:layout_constraintHorizontal_chainStyle有三個不同的取值,分別是spread、packed、spread_inside,不同的屬性值和寬高值設定可以實現不同的效果,如上面介紹,如果還不是很清楚,稍後會附上原始碼。

guideLine(輔助線)

guideLine也是CL在1.1版本新增的功能,主要用於輔助佈局,即類似為輔助線,橫向的、縱向的。該佈局是不會顯示到介面上的。提供了三個屬性:

layout_constraintGuide_begin
layout_constraintGuide_end
layout_constraintGuide_percent

先來看一下其實現

<android.support.constraint.ConstraintLayout 
...>
    <!--輔助線1 豎直輔助線,距離左側100dp-->
    <android.support.constraint.Guideline
        android:id="@+id/guide_line"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="100dp"
        />

    <!--豎直線2 水平輔助線,距離上測150dp-->
    <android.support.constraint.Guideline
        android:id="@+id/guide_line1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_begin="150dp" />

    <!--button1位置在兩個輔助線的交點位置,通過兩個輔助線來控制控制元件位置-->
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button1"
        app:layout_constraintBottom_toBottomOf="@id/guide_line1"
        app:layout_constraintStart_toStartOf="@id/guide_line" />

    <!--button2 上下居中,並且左側依賴於guide_line的輔助線顯示-->
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@id/guide_line"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

上面的XML程式碼中,我們添加了兩個GuideLine輔助線,button1的位置在兩個輔助線的交點處,button2左側依賴於guide_line的輔助線顯示並且上下居中顯示,實現出來的效果如圖:

在這裡插入圖片描述在這裡插入圖片描述

在guideLine控制元件中,通過設定

android:orientation 

來區分是豎直還是水平輔助線

總結

到這裡,ConstraintLayout的屬性大致介紹完成了,寫上面的程式碼示例我們根本就沒有使用巢狀佈局,這也是ConstraintLayout的另一個比較牛的功能,減少了View層級的巢狀,降低了介面的渲染繪製層,下面總結下本文介紹到的所有的屬性

constraint 屬性

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_constraintBaseline_toBaselineOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf

MATCH_CONSTRAINT

android:layout_width=”0dp”
android:layout_height=”0dp”

Bias偏移量設定

app:layout_constraintHorizontal_bias
app:layout_constraintVertical_bias

CircularPositioning 圓形定位

app:layout_constraintCircle
app:layout_constraintCircleRadius
app:layout_constraintCircleAngle

Margin

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom

Ratio

app:layout_constraintDimensionRatio=”2:1”
app:layout_constraintDimensionRatio=”H,2:1”
app:layout_constraintDimensionRatio=”w,2:1”

Chains(鏈條)

app:layout_constraintHorizontal_chainStyle 
取值:spread、packed、spread_inside

GuideLine(輔助線)

layout_constraintGuide_begin
layout_constraintGuide_end
layout_constraintGuide_percent
android:orientation 通過這個屬性來區分是豎直的還是水平的輔助線