學習使用ConstraintLayout佈局實戰

版權聲明:本文爲博主原創文章,未經博主容許不得轉載。 https://blog.csdn.net/dingshuhong_/article/details/80195498

1、概述

ConstraintLayout 佈局已經出來有一兩年了,最早開始由於視圖化的佈局,因此一直沒有使用過,最近瀏覽其餘博客的時候,屢次看到ConstraintLayout 是官方推薦使用的佈局,並且相對於其餘的四大布局,有不少性能方面的優點。因此有必要學習和使用一下這個佈局。下面開始吧!
引入依賴(已經到1.1版本了,是應該多嘗試使用這個佈局了)android

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

2、效果展現

不喜歡視圖化佈局,其實也能夠手寫屬性來佈局。下面展現下我看hongyang大神博客時手寫佈局的效果。
佈局效果
下面是佈局xml代碼:markdown

<?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">

    <ImageView  android:id="@+id/img_banner" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="15dp" android:background="@color/colorPrimaryDark" app:layout_constraintDimensionRatio="H,16:9" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" />

    <ImageView  android:id="@+id/img_left" android:layout_width="146dp" android:layout_height="86dp" android:layout_marginBottom="10dp" android:layout_marginLeft="12dp" android:layout_marginTop="10dp" android:background="@color/colorPrimary" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/img_banner" />

    <TextView  android:id="@+id/txt_content" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="馬雲:一年交稅170多億馬雲:一年交稅170多億馬雲:一年交稅170多億" app:layout_constraintLeft_toRightOf="@+id/img_left" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="@+id/img_left" />

    <TextView  android:layout_width="0dp" android:layout_height="wrap_content" android:text="8分鐘前" app:layout_constraintBottom_toBottomOf="@+id/img_left" app:layout_constraintLeft_toLeftOf="@+id/txt_content" />

    <TextView  android:layout_width="60dp" android:layout_height="60dp" android:background="@color/colorPrimary" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintHorizontal_bias="0.9" app:layout_constraintVertical_bias="0.9"/>
    <TextView  android:id="@+id/tab1" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/darker_gray" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@+id/tab2" />

    <TextView  android:id="@+id/tab2" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/holo_green_light" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintLeft_toRightOf="@+id/tab1" app:layout_constraintRight_toLeftOf="@+id/tab3" />

    <TextView  android:id="@+id/tab3" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/holo_red_light" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintLeft_toRightOf="@+id/tab2" app:layout_constraintRight_toRightOf="parent" />

</android.support.constraint.ConstraintLayout>

3、屬性介紹

結合這個上面這個佈局介紹下ConstraintLayout的屬性吧app

一、相對位置(Relative positioning)

在橫向和縱向上添加約束關係來固定控件位置,官方一共提供給咱們這些相對約束屬性:這裏寫圖片描述
下面咱們對比下效果
沒有添加約束佈局

<?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:layout_width="match_parent" android:layout_height="match_parent">

    <Button  android:id="@+id/btn_01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按鈕01"/>

    <Button  android:id="@+id/btn_02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按鈕2"/>

</android.support.constraint.ConstraintLayout>

沒有添加按鈕2在按鈕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:layout_width="match_parent" android:layout_height="match_parent">

    <Button  android:id="@+id/btn_01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按鈕01"/>

    <Button  android:id="@+id/btn_02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按鈕2" app:layout_constraintLeft_toRightOf="@+id/btn_01"/>

</android.support.constraint.ConstraintLayout>

沒有添加約束沒有添加按鈕2在按鈕1的右邊的約束
僅僅添加了一個app:layout_constraintLeft_toRightOf="@+id/btn_01"屬性就能夠達到了RelativeLayout佈局的android:layout_toLeftOf="@id/btn_1"所要的效果。
相對位置的約束屬性的格式基本是layout_constraintxxx_toxxxOf=id這種格式,理解起來其實並不難,constraintxxx表明當前控件的約束方向,如上圖的效果constraintLeft就是就是btn_02按鈕的左邊約束。toxxxOf被約束的控件的方向,如上圖id是btn_01 就表明與id爲btn_01控件的右邊方向約束在一塊兒。app:layout_constraintLeft_toRightOf="@+id/btn_01"結合起來就是當前控件btn_01按鈕的左邊與id爲btn_01的控件的右邊相約束。 關於約束這個詞的理解,你能夠理解成用帶彈性的繩子相鏈接起來。
下面在展現幾個例子:
按鈕01 在按鈕02的正下方學習

<?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:layout_width="match_parent" android:layout_height="match_parent">

    <Button  android:id="@+id/btn_01" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" android:text="按鈕01"/>

    <Button  android:id="@+id/btn_02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按鈕2" app:layout_constraintLeft_toLeftOf="@+id/btn_01" app:layout_constraintTop_toBottomOf="@+id/btn_01" app:layout_constraintRight_toRightOf="@+id/btn_01"/>


</android.support.constraint.ConstraintLayout>

首先對按鈕01 使用app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintTop_toTopOf="parent" 使得按鈕01的左邊和頂部與父佈局的左邊和頂部約束,這樣按鈕就被固定在左上角。 而後對按鈕02 使用app:layout_constraintLeft_toLeftOf="@+id/btn_01"將按鈕02的左邊與按鈕01的左邊相約束,而後使用app:layout_constraintTop_toBottomOf="@+id/btn_01" 讓按鈕02的頂部與按鈕01的底部相約束,這樣按鈕02就在按鈕01的正下方。最後使用 app:layout_constraintRight_toRightOf="@+id/btn_01" 讓按鈕02的右邊與按鈕01的右邊相約束,保持永遠對齊。google

二、傾向(bias)

這裏寫圖片描述
傾向分爲兩個方向 橫向和縱向, 也就是說左右和上下兩邊出現受力不均,形成傾向,好比左邊約束的力是右邊約束的力之比是9:1atom

<?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:layout_width="match_parent" android:layout_height="match_parent">

    <Button  android:id="@+id/btn_01" android:layout_width="180dp" android:layout_height="wrap_content" android:layout_marginLeft="80dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" android:text="按鈕01"/>

    <Button  android:id="@+id/btn_02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按鈕2" app:layout_constraintTop_toTopOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintVertical_bias="0.3" app:layout_constraintHorizontal_bias="0.9"/>


</android.support.constraint.ConstraintLayout>

這裏寫圖片描述
理解:左邊的間距佔左右邊間距之和的90%,上間距占上下間距之和的30%spa

三、圓心定位

這是在1.1版本添加的新屬性,貌似沒有自動提示
這裏寫圖片描述.net

<?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:layout_width="match_parent" android:layout_height="match_parent">

    <Button  android:id="@+id/btn_01" android:layout_width="80dp" android:layout_height="wrap_content" android:layout_marginLeft="80dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:text="按鈕01"/>

    <Button  android:id="@+id/btn_02" android:layout_width="80dp" android:layout_height="wrap_content" android:text="按鈕2" app:layout_constraintCircle="@+id/btn_01" app:layout_constraintCircleRadius="90dp" app:layout_constraintCircleAngle="20"/>


</android.support.constraint.ConstraintLayout>

這裏寫圖片描述
圓心定位意思就是基於兩個控件的中心,經過radius和angle來控制控件的位置。angle角度不支持負值。默認以被定位控件(btn_01)的Y軸正方向爲零度。

四、可見性約束

隱藏前隱藏後
能夠看到區別開始是按鈕01左邊約束父佈局的左邊,而後按鈕02約束按鈕01的右邊。 可是當按鈕01隱藏之後,按鈕02直接約束到父佈局的左邊,事實上按鈕根本沒有約束父佈局的左邊。 這裏小編的理解,就是以前的隱藏的控件的佈局約束依然有效,只不過按鈕01的全部邊距變成了0.若是你有更好的理解請告訴我,謝謝。

五、控件尺寸約束

一般咱們定義控件的長和寬,android:layout_width=""android:layout_height="" 來設置控件的大小。
ConstraintLayout佈局設置方式:

  • 固定值
  • wrap_content
  • 0dp(至關於MATCH_CONSTRAINT)

那match_parent呢?看下面這段話

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」.

大概意思是不推薦使用match_parent在ConstraintLayout佈局中設置大小,相似的功能可使用約束設置左右或者上下指定約束到父佈局上。
那怎樣實現其餘四大布局match_parent沾滿父窗體剩下控件的效果呢? 可使用0dp來代替
match_parent的效果

<?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">

    <Button  android:id="@+id/btn_01" android:layout_width="80dp" android:layout_height="wrap_content" android:layout_marginLeft="48dp" android:layout_marginTop="112dp" android:text="按鈕01" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent"/>

    <Button  android:id="@+id/btn_02" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="按鈕2" app:layout_constraintLeft_toRightOf="@+id/btn_01" app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>

這裏寫圖片描述
0dp實現的效果

<?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">

    <Button  android:id="@+id/btn_01" android:layout_width="80dp" android:layout_height="wrap_content" android:layout_marginLeft="48dp" android:layout_marginTop="112dp" android:text="按鈕01" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent"/>

    <Button  android:id="@+id/btn_02" android:layout_width="0dp" android:layout_height="wrap_content" android:text="按鈕2" app:layout_constraintLeft_toRightOf="@+id/btn_01" app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>

這裏寫圖片描述

六、比例(Ratio)

app:layout_constraintDimensionRatio="H,16:9"
app:layout_constraintDimensionRatio="W,16:9"

這裏的比例指的是佔父佈局的高度和寬度的比例

七、鏈條(Chains)

鏈條適合於橫向或者縱向一排的控件的佈局方式。
首先要建立一個鏈條,就是一排控件首位相互約束,以下圖
這裏寫圖片描述
這裏寫圖片描述
相似的效果的代碼像這樣,建立了一個鏈條

<?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">
    <TextView  android:id="@+id/tab1" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/darker_gray" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@+id/tab2" />

    <TextView  android:id="@+id/tab2" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/holo_green_light" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toRightOf="@+id/tab1" app:layout_constraintRight_toLeftOf="@+id/tab3" />

    <TextView  android:id="@+id/tab3" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/holo_red_light" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toRightOf="@+id/tab2" app:layout_constraintRight_toRightOf="parent" />

</android.support.constraint.ConstraintLayout>

效果就像這樣
這裏寫圖片描述
看似效果跟LinearLayout的比重佈局很類似,可是它有和LinearLayout不同的效果,就是給鏈條添加樣式。
這裏寫圖片描述

  • CHAIN_SPREAD 元素被分散開(默認樣式)
  • 在CHAIN_SPREAD模式下,若是一些控件被設置爲MATCH_CONSTRAINT,那麼控件將會把全部剩餘的空間均分後「吃掉」
  • CHAIN_SPREAD_INSIDE Chain兩邊的元素貼着父容器,其餘元素在剩餘的空間中採用CHAIN_SPREAD模式
  • CHAIN_PACKED Chain中的全部控件合併在一塊兒後在剩餘的空間中居中

4、總結

看完了關於ConstraintLayout佈局屬性的介紹,是否是感受很是強大,不只有豐富的相對位置約束,還有比例、傾向的設置,具有RelativeLayoutLinearLayout兩個最經常使用佈局的各類優勢。關鍵在性能上也有優點,咱們還有什麼理由不嘗試呢?
參考連接:
https://developer.android.google.cn/reference/android/support/constraint/ConstraintLayout
http://www.javashuo.com/article/p-vvqpebme-bt.html

相關文章
相關標籤/搜索