再不用ContraintLayout就out啦

ContraintLayout 屬性

本文基於ContraintLayout 1.1版本, 參考ContraintLayout官方文檔並結合實際的例子說明android

ContraintLayout 有如下做用:app

  • Relative positioning 相對位置
  • Margin 邊距
  • Centering position 中間位置
  • Visibility behavior 可見性行爲
  • Dimension constraints 尺寸約束
  • Chains 鏈
  • Virtual Helpers objects 虛擬幫助工具類
  • Optimizer 優化

相對位置

相似於RelativeLayout佈局,例如:相對父類的最左邊,相對某個View的左邊 等等ide

這種屬性有不少,就舉例兩個屬性:工具

  • layout_constraintLeft_toLeftOf 自身的左邊相對於誰的左邊, 若是相對於父View,就用parent
  • layout_constraintLeft_toRightOf 自身的左邊相對於誰的右邊, 若是相對於父View,就用parent

邊距

邊距屬性繼承ViewGroup.LayoutParam, 以下所示:佈局

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

可是須要注意的是:優化

  • 設置的邊距必須>= 0 。ui

  • 設置的邊距要和正確的相對位置約束一塊兒使用纔有效過,例如:this

    app:layout_constraintTop_toTopOf="parent"
    android:layout_marginTop="10dp"
    //layout_marginTop要和layout_constraintTop_x 一塊兒使用纔有效,單獨layout_marginTop是無效的
    複製代碼

View的可見或不可見時呈現不一樣邊距

用於設置某個View隱藏時的邊距。需求有時A-View的可見或不可見時,B-View的邊距會呈現不一樣的邊距 。這是能夠用到以下屬性:spa

  • layout_goneMarginStart
  • layout_goneMarginEnd
  • layout_goneMarginLeft
  • layout_goneMarginTop
  • layout_goneMarginRight
  • layout_goneMarginBottom

可是須要注意的是:3d

  • 設置的邊距要和正確的相對位置約束一塊兒使用, 而且這個約束是做用在目標View時纔有效過,例如:

    <TextView android:id="@+id/tv_a" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintRight_toRightOf="parent" android:visibility="gone" />
    <TextView android:id="@+id/tv_b" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintRight_toLeftOf="@+id/tv_a" app:layout_goneMarginRight="20dp" />
    // layout_goneMarginRight 這是屬性是設置右邊距,
    // 要與layout_constraintRight_toLeftOf結合使用採用效果。
    // layout_constraintRight_toLeftOf屬性是自身view的右邊相對
    // 於tv_a的左邊,也就是自身的view在tv_a的左邊,只有在tv_a的左邊時,
    // tv_a隱藏了layout_goneMarginRight纔有效果。
    複製代碼

中間位置與偏移量

<android.support.constraint.ConstraintLayout ...>
    <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"/>
複製代碼

看上面的代碼,一個Button在父類左邊, 同時又在父類右邊,若是這個Button的寬度不是和父View相同就不可能同時知足兩個條件。可是父類是ConstraintLayout佈局,這個Button的寬度小於父View的寬度時,同時設置app:layout_constraintLeft_toLeftOf="parent", app:layout_constraintRight_toRightOf="parent"時會使該Button位於父類的中心。layout_constraintLeft_toLeftOf, layout_constraintRight_toRightOf 這兩個屬性也能夠做用於其餘View,達到位於該View中心位置。

Bias 偏移量

當A同時設置了layout_constraintLeft_toLeftOf和layout_constraintRight_toRightOf在一個B-View時, 你還能夠經過layout_constraintHorizontal_bias屬性移動A在B-View某個位置上。layout_constraintHorizontal_bias的值是0-1之間,0.5 就是在B-View的中間。

同理layout_constraintVertical_bias 是做用在垂直方向上的,結合layout_constraintBottom_toBottomOf和layout_constraintTop_toTopOf使用。

<android.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" >
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintHorizontal_bias="0.3333" android:gravity="center" android:textSize="18sp" android:text="HHHHHHH" />
</android.support.constraint.ConstraintLayout>
複製代碼

contrainst_h_bia

稍微解析一下bias這個屬性,以layout_constraintHorizontal_bias爲例,看上面的代碼和效果圖,水平bias屬性設置了0.3333, 大約是1/3。 上圖中C爲手機的左邊緣,D爲手機右邊緣,A和B分別是TextView的左右邊緣。

0.3333 = CA / BD。不少人會誤覺得CA / CD, 這個要注意。總結起來就是bias屬性的值等於該View左邊到父view左邊距離 除以該View右邊到父view右邊距離

Circular positioning 圓形位置

你能夠約束一個View的中心相對於另外一個View的中心。

  • layout_constraintCircle : references another widget id 另外一個View的id
  • layout_constraintCircleRadius : the distance to the other widget center。半徑
  • layout_constraintCircleAngle : which angle the widget should be at (in degrees, from 0 to 360) 角度

contrainst_01

可能有些人以爲沒卵用,下面舉個栗子:

先來效果張圖,有張小圓圖的圓心須要放在一張大圖的下面中心位置,(用相對佈局之類很差搞了吧.....)

constrainst_circle

<ImageView android:id="@+id/iv_shop_big_photo" android:layout_height="200dp" tools:srcCompat="@drawable/ic_big_shop" android:layout_width="match_parent" android:scaleType="fitXY" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" />

    <ImageView android:id="@+id/iv_shop_logo" android:layout_width="56dp" android:layout_height="56dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" tools:srcCompat="@drawable/ic_home_category" app:layout_constraintCircle="@+id/iv_shop_big_photo" app:layout_constraintCircleRadius="100dp" app:layout_constraintCircleAngle="180" />
複製代碼

上面代碼就能達到效果啦,半徑爲大圖高的一半,角度是180度。

Visibility behavior 可見性行爲

就佈局計算而言,GONE的View仍然是其中的一部分,具備重要的區別:

  • 對於佈局的傳遞,它們的尺寸將被視爲零(基本上,它們將被解析爲一個點)

  • 若是他們對其餘小部件有約束,約束仍然有效,但任何邊距都會等於零

Dimensions constraints 尺寸約束

最低限度尺寸

  • android:minWidth set the minimum width for the layout

  • android:minHeight set the minimum height for the layout

  • android:maxWidth set the maximum width for the layout

  • android:maxHeight set the maximum height for the layout

    ConstraintLayout的子View設置wrap_content時纔有效

尺寸約束

android:layout_width andandroid:layout_height 有三種值:

  • 準確的值,例如10dp

  • wrap_content

  • 0dp至關於match_contraint, 能夠結合約束來限制寬高尺寸。

    官方推薦:少用match_parent, 多用0dp

    當使用0dp,沒加任何約束屬性,就等於match_parent

強制約束

當設置了wrap_content, 約束不會限制view的尺寸。當時你能夠用app:layout_constrainedWidth="true|false"或者app:layout_constrainedHeight=」true|false」來約束尺寸, 設置true就是約束。

下面舉個栗子:

<ConstraintLayout>
<View android:id="@+id/view" android:layout_width="320dp" android:layout_height="24dp" app:layout_constraintLeft_toLeftOf="parent" />

<TextView android:id="@+id/tv_c" android:layout_width="wrap_content" android:layout_height="wrap_content" android:lines="1" app:layout_constrainedWidth=」true|false」 // 默認是false app:layout_constraintLeft_toRightOf="@+id/view" app:layout_constraintRight_toRightOf="parent" android:text="ABCDEFGHI" />
</ConstraintLayout>
複製代碼

圖一

constraint_width_false_

圖二

constraint_width_true

圖一沒有app:layout_constrainedWidth屬性,該屬性默認是false; 圖二app:layout_constrainedWidth的屬性爲true。TextView 雖然設置了layout_constraintLeft_toRightOf在紅色View的右邊約束,但並無限制寬度,須要用layout_constrainedWidth屬性來限制寬度。

0dp使用

針對約束來限制大小,還有一些屬性:

  • layout_constraintWidth_min and layout_constraintHeight_min : will set the minimum size for this dimension 設置最小尺寸
  • layout_constraintWidth_max and layout_constraintHeight_max : will set the maximum size for this dimension 設置最大尺寸
  • layout_constraintWidth_percent and layout_constraintHeight_percent : will set the size of this dimension as a percentage of the parent 設置百分比

上面這些屬性須要設置了0dp才能生效。下面舉些個栗子:

  • 栗子1,設置了layout_width="0dp", app:layout_constraintWidth_min="50dp", 限制了最小寬度爲50dp
<android.support.constraint.ConstraintLayout>    
	<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:text="B" android:id="@+id/tv_b" />
    <TextView android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="@+id/tv_b" app:layout_constraintWidth_min="50dp" android:gravity="center" android:textSize="18sp" android:lines="1" android:text="A" />
</android.support.constraint.ConstraintLayout>
複製代碼

contrainst_min

  • 栗子2, app:layout_constraintWidth_percent="0.5" 設置了寬度爲父View寬的一半
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" ![](https://user-gold-cdn.xitu.io/2019/1/4/168176735e1d9c4f?w=624&h=200&f=png&s=36404) app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:text="B" android:id="@+id/tv_b" />

    <TextView android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="@+id/tv_b" app:layout_constraintWidth_percent="0.5" android:gravity="center" android:textSize="18sp" android:lines="1" android:text="A" />
複製代碼

contrainst_percent

比例

你能夠定義寬和高之間比例。設置寬高比例至少一邊尺寸設置爲0dp, 要有個基準(基於寬仍是高), 屬性以下:

  • layout_constraintDimensionRatio 它的值能夠是float,也能夠是width:height, 當沒有基準時,能夠(W/H,width:height)
<android.support.constraint.ConstraintLayout>
        <TextView android:layout_width="wrap_content" android:layout_height="0dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintDimensionRatio="1:2" android:gravity="center" android:textSize="18sp" android:text="ABCD" />
</android.support.constraint.ConstraintLayout>
複製代碼

constrainst_ratio

上面效果layout_constraintDimensionRatio設置了1:2, 就是寬 : 高 = 1 :2 , 寬爲wrap_content,高爲0dp,全部寬根據text是一個準確的寬,而後高 = 寬 x 2 , 全部就呈現了上面的效果。

下面再看個效果,

<TextView android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintDimensionRatio="1:2" android:gravity="center" android:textSize="18sp" android:text="ABCD" />
複製代碼

constrainst_ratio2

看效果圖可能會以爲有點怪,設上面例子的區別是 寬爲0dp,高爲wrap_content, 寬高比仍是1 :2。爲何會出現這個狀況,是由於基準不一樣,高爲wrap_content,因此此次高是基準, 至於爲何是這個效果,本身去看源碼,不深刻啦。

Chains 鏈

Creating a chain 建立鏈

不是什麼狀況都是鏈,若是一組View經過雙向鏈接連接在一塊兒,則它們被視爲鏈。下圖就是一個鏈:

contraist_chain

Chain heads 鏈頭

鏈的屬性是由在鏈的第一個元素上設置控制, 第一個元素被稱爲鏈頭。

constrainst_chain_heads

如上圖所示,A就是鏈頭。

鏈頭: 水平方向是最左邊的一個,垂直方向是最上面一個

Chain Style 鏈樣式

定義鏈樣式使用layout_constraintHorizontal_chainStyle 或者 layout_constraintVertical_chainStyle,分別對應水平和垂直方向, 這個屬性只做用在第一個元素(鏈頭)纔有效, 它的值有以下幾個:

  • CHAIN_SPREAD -- 元素將會被擴展 (默認的屬性)
  • Weighted chain -- 在CHAIN_SPREAD模式下, 若是一些View被設置MATCH_CONSTRAINT了,能夠利用權重等分空間
  • CHAIN_SPREAD_INSIDE -- 和CHAIN_SPREAD類似, 但鏈條的終點不會分散開來
  • CHAIN_PACKED -- 這些元素會被包在一塊兒,默認是放在中間, 能夠結合水平或者垂直bias屬性分配位置。

官方介紹圖:

constrains_chains_ex
下面一一代碼舉例:

  • Spread Chain 的效果
<android.support.constraint.ConstraintLayout>    
	<TextView android:id="@+id/tv_01" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@+id/tv_02" app:layout_constraintHorizontal_chainStyle="spread" //Spread Chain 做用與鏈頭 android:text="ABCD-01" />

    <TextView android:id="@+id/tv_02" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/tv_01" app:layout_constraintRight_toLeftOf="@+id/tv_03" android:text="ABCD-02" />


    <TextView android:id="@+id/tv_03" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/tv_02" app:layout_constraintRight_toRightOf="parent" android:text="ABCD-03" />

</android.support.constraint.ConstraintLayout>
複製代碼

spread

  • Spread Inside Chain 的效果
<android.support.constraint.ConstraintLayout>    
	<TextView android:id="@+id/tv_01" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@+id/tv_02" app:layout_constraintHorizontal_chainStyle="spread_inside" //Spread Inside Chain 做用與鏈頭 android:text="ABCD-01" />

    <TextView android:id="@+id/tv_02" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/tv_01" app:layout_constraintRight_toLeftOf="@+id/tv_03" android:text="ABCD-02" />


    <TextView android:id="@+id/tv_03" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/tv_02" app:layout_constraintRight_toRightOf="parent" android:text="ABCD-03" />

</android.support.constraint.ConstraintLayout>
複製代碼

spread_inside

  • Pick Chain 與 Pick Chain with Bias 的效果
<android.support.constraint.ConstraintLayout>    
	<TextView android:id="@+id/tv_01" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@+id/tv_02" app:layout_constraintHorizontal_chainStyle="packed" // Packed Chain app:layout_constraintHorizontal_bias="0.2" // Bias 屬性 android:text="ABCD-01" />

    <TextView android:id="@+id/tv_02" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/tv_01" app:layout_constraintRight_toLeftOf="@+id/tv_03" android:text="ABCD-02" />


    <TextView android:id="@+id/tv_03" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/tv_02" app:layout_constraintRight_toRightOf="parent" android:text="ABCD-03" />

</android.support.constraint.ConstraintLayout>
複製代碼

picked_bias

A距離左邊佔0.2比例,layout_constraintHorizontal_bias = 0.2; 當不加layout_constraintHorizontal_bias屬性時,默認是0.5, 效果以下圖:

picked

Weighted chains 權重鏈

使用權重屬性, 須要View被設置MATCH_CONSTRAINT(也就是0dp)

  • layout_constraintHorizontal_weight
  • layout_constraintVertical_weight

下面是代碼示例, 使用weight把3個View分紅1:2:2 的比例:

<android.support.constraint.ConstraintLayout>   
	<TextView android:id="@+id/tv_01" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@+id/tv_02" app:layout_constraintHorizontal_weight="1.0" android:text="ABCD-01" />

    <TextView android:id="@+id/tv_02" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/tv_01" app:layout_constraintRight_toLeftOf="@+id/tv_03" app:layout_constraintHorizontal_weight="2.0" android:text="ABCD-02" />


    <TextView android:id="@+id/tv_03" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/tv_02" app:layout_constraintRight_toRightOf="parent" app:layout_constraintHorizontal_weight="2.0" android:text="ABCD-03" />
</android.support.constraint.ConstraintLayout>
複製代碼

constraint_weight

Virtual Helper objects 虛擬助手類

Guideline

自己繼承View,0 寬度, 0高度。

  • app:layout_constraintGuide_begin 與父類左邊的距離

  • app:layout_constraintGuide_end 與父類右邊的距離

  • app:layout_constraintGuide_percent 佔父類總寬度的百分比

  • android:orientation 指引線的方向

  • <android.support.constraint.ConstraintLayout>
        <android.support.constraint.Guideline android:id="@+id/guide_line_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintGuide_percent="0.1" android:orientation="vertical" />
    
        <android.support.constraint.Guideline android:id="@+id/guide_line_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintGuide_begin="100dp" android:orientation="horizontal" />
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/guide_line_vertical" app:layout_constraintTop_toTopOf="@+id/guide_line_horizontal" android:text="Guide Line" />
    </android.support.constraint.ConstraintLayout>
    複製代碼

constraint_guide_line

Barrier

Barrier自己繼承View,0 寬度, 0高度。做用:引用多了View建立一個屏障。

  • barrierDirection 方向
  • constraint_referenced_ids View ids 用逗號隔開

下面用一個場景來講明:

barriar

如上圖所示,3個TextView, C在 A和B右邊,可是A,B長度不定。一般咱們能夠用一個ViewGroup包含A和B,C在那個ViewGroup的右邊就能夠啦。可是這樣就多了一層佈局,ConstraintLayout目的是減小層級,這時Barrier就能夠發揮做用力,Barrier能夠在A和B最右邊建立一個豎立屏障,C約束在這個屏障便可。

代碼以下:

<android.support.constraint.ConstraintLayout>
   <TextView
        android:id="@+id/tv_b_01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/s_01"
        app:layout_constraintTop_toBottomOf="@+id/tv_b_02"
        app:layout_constraintLeft_toLeftOf="parent"
        />
    <TextView
        android:id="@+id/tv_b_02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        android:text="@string/s_02" />

    <android.support.constraint.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="end"
        app:constraint_referenced_ids="tv_b_01,tv_b_02"
        />
    <TextView
        android:id="@+id/tv_right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="15dp"
        android:layout_marginLeft="15dp"
        android:text="@string/s_content"
        app:layout_constraintLeft_toRightOf="@+id/barrier" />
</android.support.constraint.ConstraintLayout>
複製代碼

barriar

barriar

Group

Group自己繼承View,0 寬度, 0高度。

用來控制一羣View的可見性,代碼實例:

<TextView android:id="@+id/tv_center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ABCDEFG" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" />

    <TextView android:id="@+id/tv_111" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="HIJKLMN" app:layout_constraintTop_toBottomOf="@+id/tv_center" app:layout_constraintLeft_toLeftOf="@+id/tv_center" />

    <android.support.constraint.Group android:id="@+id/group" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" app:constraint_referenced_ids="tv_center, tv_111" />
複製代碼

如上面代碼所示,Group使用constraint_referenced_ids屬性把兩個view的id弄成了一個羣體,把這兩個view隱藏啦。Group也能夠代碼去控制。

Optimizer 優化

使用屬性app:layout_optimizationLevel="direct|barrier|chain"制定優化

  • none : 沒有任何優化
  • standard : 默認 (direct and barrier)
  • direct : 優化直接約束
  • barrier : 優化barrier屏障約束
  • chain : 優化鏈約束 (實驗功能)
  • dimensions : 優化View的測量 (實驗功能), 減小測量次數
相關文章
相關標籤/搜索