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 通過這個屬性來區分是豎直的還是水平的輔助線