ConstraintLayout 學習總結

ConstraintLayout 的簡介

1.ConstraintLayout,中文稱約束佈局,在2016年Google I/O大會時提出,2017年2月發佈正式版,目前穩定版本爲1.0.2。約束佈局做爲Google從此主推的佈局樣式,能夠徹底替代其餘佈局,下降頁面佈局層級,提高頁面渲染性能。android

2.ConstraintLayout的優劣 優勢:當佈局出現多層嵌套的時候,使用ConstraintLayout能夠減小布局嵌套,平時咱們基本都是用LinearLayout和RelativeLayout,一層LinearLayout嵌套會致使onMeasure測量兩次,而RelativeLayout是四次,雖然咱們感受不到,爲了更好就要項目性能和提高自我,有必要去學習一下。另一點ConstraintLayout也向下兼容到API 9,因此你再也沒有理由不用了。 缺點:當佈局沒嵌套的時候,ConstraintLayout要想實現一些效果須要設置太多的屬性,相對於我的來講比較繁瑣。git

3.若是使用以及要求 第一步:在project的build.gradle設置谷歌的遠程倉庫github

repositories {
    maven {
        url 'https://maven.google.com'
    }
}
複製代碼

第二步:在要使用ConstraintLayout的module的build.gradle文件中引入約束佈局庫canvas

dependencies {
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
}
複製代碼

ConstraintLayout 屬性介紹

####相對位置屬性bash

layout_constraintTop_toTopOf — 指望視圖的上邊對齊另外一個視圖的上邊。
layout_constraintTop_toBottomOf — 指望視圖的上邊對齊另外一個視圖的底邊。
layout_constraintTop_toLeftOf — 指望視圖的上邊對齊另外一個視圖的左邊。
layout_constraintTop_toRightOf — 指望視圖的上邊對齊另外一個視圖的右邊。
layout_constraintBottom_toTopOf — 指望視圖的下邊對齊另外一個視圖的上邊。
layout_constraintBottom_toBottomOf — 指望視圖的底邊對齊另外一個視圖的底邊。
layout_constraintBottom_toLeftOf — 指望視圖的底邊對齊另外一個視圖的左邊。
layout_constraintBottom_toRightOf — 指望視圖的底邊對齊另外一個視圖的右邊。
layout_constraintLeft_toTopOf — 指望視圖的左邊對齊另外一個視圖的上邊。
layout_constraintLeft_toBottomOf — 指望視圖的左邊對齊另外一個視圖的底邊。
layout_constraintLeft_toLeftOf — 指望視圖的左邊對齊另外一個視圖的左邊。
layout_constraintLeft_toRightOf — 指望視圖的左邊對齊另外一個視圖的右邊。
layout_constraintRight_toTopOf — 指望視圖的右邊對齊另外一個視圖的上邊。
layout_constraintRight_toBottomOf — 指望視圖的右邊對齊另外一個視圖的底邊。
layout_constraintRight_toLeftOf — 指望視圖的右邊對齊另外一個視圖的左邊。
layout_constraintRight_toRightOf — 指望視圖的右邊對齊另外一個視圖的右邊。
複製代碼

以上屬性都是設置當前控件相對控件的位置關係,以layout_constraintLeft_toLeftOf=@id/btn_A爲例子,其中layout_部分是固定格式,分爲兩部分,第一部分constraintLeft是表示當前控件的左邊界,toLeftOf表明就是當前控件在btn_A的左邊,app:layout_constraintBaseline_toBaselineOf="@id/btn_A" 這個比較特殊,這個至關於當前的控件的水平中心線與btn_A的水平中心線爲準,下面是例子app

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_relative_position"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="zr.com.constraintdemo.normal.RelativePositionActivity">

    <Button
        android:id="@+id/btn_A"
        android:text="A"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        />

    <Button
        android:text="在A下方,與A左對齊"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/btn_A"
        app:layout_constraintLeft_toLeftOf="@id/btn_A"
        android:layout_marginTop="32dp"
        />

    <Button
        android:text="在A上方,與A居中對齊"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@id/btn_A"
        app:layout_constraintLeft_toLeftOf="@id/btn_A"
        app:layout_constraintRight_toRightOf="@id/btn_A"
        android:layout_marginBottom="32dp"
        />

    <Button
        android:text="baseline對齊"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        app:layout_constraintBaseline_toBaselineOf="@id/btn_A"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginLeft="8dp"
        android:gravity="bottom"
        />

    <Button
        android:text="水平居中對齊"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:gravity="bottom"
        app:layout_constraintTop_toTopOf="@id/btn_A"
        app:layout_constraintBottom_toBottomOf="@id/btn_A"
        app:layout_constraintLeft_toRightOf="@id/btn_A"
        android:layout_marginLeft="16dp"
        />

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

相對位置的總結:maven

  • 一個控件通常只須要相對於一個控件設置相對位置,與Java的單繼承類似,除了鏈表結構,後面會提到
  • 設置app:layout_constraintBaseline_toBaselineOf="@id/btn_A"屬性以後 再設置上下位置的約束無效,設置左右的約束屬性仍是有效的

####偏移屬性(BIAS)ide

在設置控件的居中屬性以後,經過偏移屬性能夠設置讓控件更偏向於依賴控件的某一方,偏移設置爲0~1之間的值。相應屬性:工具

  • layout_constraintHorizontal_bias // 水平偏移
  • layout_constraintVertical_bias // 垂直偏移

舉個例子:佈局

<Button
        android:text="水平偏移30%"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_bias="0.3"
        />
複製代碼

QQ圖片20171201144606.png
這個例子是最上面哪一個水平偏移30%的 關於偏移屬性的總結:

  • 設置偏移以前必定要設置一個相對位置,若是沒有相對位置,偏移時無效的
  • 設置的相對位置必定要是 ,app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
  • 水平方向的必定要先設置app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" 垂直方向的必定要設置app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"
  • 偏移值默認從0-1的數字,固然也能夠設置負數和大於1的數字,可是效果就是顯示在屏幕外
  • 水平偏移量是屏幕寬度的偏移倍數,垂直偏移時屏幕高度的偏移倍數

####可見性屬性(VISIBILITY)

#####(一) 當控件設置GONE的時候,雖然控件GONE了,可是控件之間的約束條件還在 例子以下:

<?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:id="@+id/activity_bias"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:visibility="gone"
        android:id="@+id/btn_A"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="A"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <Button
        android:layout_width="wrap_content"
        android:layout_height="60dp"
        android:layout_marginLeft="16dp"
        android:gravity="center"
        android:text="與A水平居中對齊"
        app:layout_constraintBottom_toBottomOf="@id/btn_A"
        app:layout_constraintLeft_toRightOf="@id/btn_A"
        app:layout_constraintTop_toTopOf="@id/btn_A" />

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

效果

QQ圖片20171201152727.png
#####(二) 控件設置爲GONE的時候,也能夠設置GONE以後的app:layout_goneMarginLeft="100dp" ,有些時候想實現特殊效果可使用

####尺寸約束

  • minWidth :最小寬度,即便沒有內容時也要佔有minWidth 的寬度,前提是寬度屬性android:layout_width="wrap_content" ,當內容的時候寬度大於minWidth 時,控件寬度自動擴充
  • 填充模式:相似LinearLayout 的android:layout_weight="1"屬性,區別就是,若是想水平方向最大填充,設置android:layout_width="0dp",必定要設置,不然無效,同理垂直方向。
  • constrainedWidth:constrainedWidth有兩個值,當爲true的時候就開啓了控件的最小寬度或者高度,不然相反,配合layout_constraintWidth_min屬性設置最小寬度,須要注意的是,當屬性中存在minWidth 時,這個屬性是失效的,以minWidth 爲準
  • 百分比佈局:首先必需要設置app:layout_constraintWidth_default="percent" app:layout_constraintHeight_default="percent"這兩個屬性 ,還有android:layout_width="0dp" android:layout_height="0dp"屬性,不然以後設置的都是無效的, app:layout_constraintWidth_percent="0.5" app:layout_constraintHeight_percent="0.3"設置這兩個就能夠實現相對於屏幕的百分比寬高了

####控件寬高比(RATIO)

這個對於咱們開發者簡直就是福利,若是是動態設置寬高相對麻煩。 layout_constraintDimentionRatio屬性表明設置控件寬高的比例,前提是控件的寬高必須有一個設置爲0dp,不然不去做用

  • 第一種方式:直接設置一個float值,表示寬高比,記住是寬高比,寬高比!!!
app:layout_constraintDimensionRatio="2"
複製代碼
  • 第二種方式:使用比值,例如 :
app:layout_constraintDimensionRatio="16:9"
或者
app:layout_constraintDimensionRatio="H,16:9"
複製代碼

這種方式,若是沒有前綴就表明是寬高比,若是加了前綴H表明比值的第一個數字是高度,W是寬度

說明:這裏面坑不少,這裏就一一簡單的介紹一下,若是寬高都設置的屬性爲0dp,首先屏幕高度確定大於寬度,因此寬度上面必定處於填充狀態,這0-1之間有個值正好是屏幕寬高比,這時候控件正好填充屏幕,若是想不想寬度被填充至少要保證寬高其中一個屬性的值不爲0dp,只要有一個屬性不爲0dp的時候,這時候比例的根據就是內容的填充寬高來定而不是屏幕。當寬高兩個值都不爲0dp的時候,這時候比例屬性無效。而且這個比例會自動計算內容是否須要換行展現更好的比例,因此很是智能。

####鏈式約束(CHAIN)

鏈這個概念是約束佈局新提出的,它提供了在一個維度(水平或者垂直),管理一組控件的方式。

1728184-af9bd09ddec63651.png
處於水平或者垂直方向第一個控件爲chain head(鏈頭),當咱們給chain head設置layout_constraintHorizontal_chainStyle或layout_constraintVertical_chainStyle,整條鏈的狀態將會發生改變。

  • CHAIN_SPREAD – 元素之間的空間將會均勻分佈,這是系統默認的排列方式

  • CHAIN_SPREAD – 首尾的兩條鏈將不會分配空間,其他內部的鏈將均勻分配空間。

  • CHAIN_PACKED – 首尾兩條鏈將會分配空間,鏈內部將不會分配空間

  • Weight 經過設置的weight值來分配元素的寬或者高

1728184-3f72d2f2cc29e797.png
注意:

  • layout_constraintHorizontal_chainStyle屬性值是小寫的,文檔裏給出的是大寫的。

  • weight樣式的實現有一個前提,chainStyle必須爲默認的spread樣式

  • 設置Weight樣式時記得把元素中的寬或者設置成0dp

Guideline

首先說明一下,Guideline只能用於ConstraintLayout中,是一個工具類,不會被顯示,僅僅用於輔助佈局。 它能夠是horizontal或者 vertical的。(例如:android:orientation="vertical")

  • vertical的Guideline寬度爲零,高度爲ConstraintLayout的高度
  • horizontal的Guideline高度爲零,寬度爲ConstraintLayout的高度

定位Guideline有三種方式:

  • 指定距離左側或頂部的固定距離(layout_constraintGuide_begin)
  • 指定距離右側或底部的固定距離(layout_constraintGuide_end)
  • 指定在父控件中的寬度或高度的百分比(layout_constraintGuide_percent)

Guideline 的源碼以下:

public class Guideline extends View {
    public Guideline(Context context) {
        super(context);
        super.setVisibility(8);
    }
    public Guideline(Context context, AttributeSet attrs) {
        super(context, attrs);
        super.setVisibility(8);
    }
    public Guideline(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        super.setVisibility(8);
    }
    public Guideline(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr);
        super.setVisibility(8);
    }
    public void setVisibility(int visibility) {
    }
    public void draw(Canvas canvas) {
    }
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        this.setMeasuredDimension(0, 0);
    }
}
複製代碼

源碼說明:

  • 它默認是GONE的。8 就是View.GONE的值。
  • 它的public void setVisibility(int visibility)方法被空實現了,因此用戶也沒辦法改變它的可見度。
  • 推導出它必定是GONE的。在屏幕上不可見
  • this.setMeasuredDimension(0, 0); 和public void draw(Canvas canvas)的空實現,代表這是一個超輕量的View,不可見,沒有寬高,也不繪製任何東西。僅僅做爲咱們的錨點使用。

##總結 ConstraintLayout佈局剛開始學習的時候確實很是麻煩,可是全部的新鮮事物都是入手難,光理論確定是不行的,總之本身動手豐衣足食。我本身也作個了demo傳送門,能夠方便參考,謝謝你們提供意見!

相關文章
相關標籤/搜索