說明
這次 IO 給開發(fā)者帶來了很多驚喜, ConstraintLayout 是其中較為實用的之一. Google 第一時間發(fā)布了官方的代碼實驗室指導教程, 從樣例項目和實驗操作出發(fā)一步步理解 ConstraintLayout. 這里是我的翻譯.
同步于我的博客: http://quanqi.org/2016/05/20/code-labs-constraint-layout/ (簡書的圖片都換行了, 我的博客上沒有這個問題)
英文原文: https://codelabs.developers.google.com/codelabs/constraint-layout/index.html
本文涉及到一些詞匯對照表:
EN | CN |
---|---|
Constraint | 約束 |
Constraint Handle | 約束手柄 |
AutoConnect | 自動連接 |
Inference | 推理 |
UI Builder | UI 生成器 |
其中 Handle 不知如何翻譯更佳, 目前想到可供選擇的有 '手柄' '紐' '軸' '操作點' '操作柄', 此文先選取最簡單的翻譯'手柄', 如果有更好的翻譯還請賜教.
概述
在此 codelab 中, 你將會學習 ConstrainLayout -- 一個構(gòu)建在靈活的約束系統(tǒng)上的新型 Layout, 由 Android Support 庫提供. 在此 Codelab 的最后, 你將能夠使用 Android Studio 中的布局編輯器建立一個相當復雜的布局(使用 ConstrainLayout).
constraint-layout 庫和 UI 生成器當期處于 preview 狀態(tài).
你將學到什么
- 新布局管理器使用的約束系統(tǒng)
- 創(chuàng)建約束以構(gòu)建靈活且高效的布局
- 新布局編輯器中的各種特性
你所需的準備
- Android Studio 2.2 preview 或者更新的版本
- 樣例代碼
獲取樣例代碼
要下載樣例代碼, 你可以選擇:
- 下載 zip
- 或者用命令行克隆 Github 倉庫
$ git clone https://github.com/googlecodelabs/constraint-layout.git
contraint-layout 倉庫包括一個工程:
- constraint-layout-start — 包含此 Codelab 中你將會構(gòu)建的 layout 的工程.
運行樣例代碼
首先, 我們來看看這個已經(jīng)完成的應用的樣子. 下載代碼后, 這個指導書講解了如何用 Android Studio 打開完整的樣例應用. 請注意此樣例需要 Android Studio 2.2 preview.
- 打開 File > New > Import Project 并從之前下載樣例代碼目錄選擇
constraint-layout-start
目錄 - 點擊
- 從工程面板打開
res/layout/activity_main_done.xml
. - 選擇 Design 標簽查看最終布局.
- 改變 UI 生成器做上的 "
Virtual Device to render the layout with
"
或者:
如果你打算在 Android 設備上運行此樣例, 打開 MainActivity.java
并確保 setContentView
方法使用參數(shù)是 activity_main_done.xml
.
setContentView(R.layout.activity_main_done);
接入你的 Android 設備并點擊
常見問題
- 如何安裝 Android Studio?
- 如何啟用 USB 調(diào)試?
- Gradle sync error: Ensure that you update the SDK Manager to use build tools version >= 23.0.2. The error message typically has a link that helps in downloading the build tools version.
約束系統(tǒng)概覽
布局引擎使用每一個控件指定的約束確定他們在布局中的位置. 你可以手動指定約束, 也可以使用 Android Studio 布局編輯器推理自動指定. 為了更好的理解約束, 讓我來看看選中空間上可用的基礎手柄.
約束
約束幫助你保持控件對齊. 你可以使用錨點(比如下圖展示的約束手柄)來確定各控件之間的對齊規(guī)則. 例如, 設置一個從 button 2 的左手柄到 button 1 的右手柄的約束(見下圖A)意味著控件 button 2 將會位于 button 1 右邊 56dp 處.
Figure A.
手柄的類型:
Figure B. 在這個控件中我們可以看到不同的手柄
改變尺寸的手柄: 類似于其它你可能已經(jīng)用過的繪圖設計程序, 調(diào)整尺寸的手柄允許你改變控件的尺寸.
側(cè)邊約束手柄: 側(cè)邊約束 handle 呈現(xiàn)為每一個控件側(cè)邊的圓圈, 可以讓你指定控件的位置. 例如, 你可以使用某個控件的左側(cè)邊約束 handle 設置控件總是位于另一個控件右邊 24dp 處. 這種手柄在此 codelab 中也被稱作錨點.
基準線約束手柄:
基準線約束 handle 幫助你對齊兩個控件的文本區(qū)域, 與控件尺寸無關(guān). 在你想使用兩個不同大小的控件同時又想保持其中文字對齊的時候很有幫助.
約束系統(tǒng)的規(guī)則
除了以下情況外, 布局中控件的錨點可以連接到其它控件的任意錨點.
- 不同軸上的錨點, 例如左邊和上邊的錨點不能相連.
- 基線約束 handle 只能與其它極限建立約束
禁止會產(chǎn)生循環(huán)的錨點連接
構(gòu)建入門項目
現(xiàn)在你已經(jīng)準備好在入門項目上構(gòu)建你的 constraint layout 了.
從左導航欄打開 res/layout/activity_main_start.xml
.
引入 constraint-layout 的依賴
constraint-layout
被構(gòu)建為一個獨立的 support 庫, 支持所有 Android 2.3(Gingrebread) 以上的 Android 版本. 本入門項目已經(jīng)在 app/build.gradle
中包含了它的依賴. 對于你打算用 ConstraintLayout
構(gòu)建的應用, 加入如下編譯依賴:
dependencies {
...
compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha'
}
定位到 res/layout/activity_main_start.xml
包含在此 codelab 項目中此 xml 布局已經(jīng)有了一個空的 ConstraintLayout
元素. ConstraintLayout
一開始就被構(gòu)建為在 UI 生成器中單獨使用.
<?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">
</android.support.constraint.ConstraintLayout>
切換到顯示為編輯器窗口底部一個標簽頁的 Design 視圖.
添加一個 ImageView 到布局中
第一個任務是添加一個 ImageView
到布局中. 在設計窗口, 找到控件選擇板上的 ImageView
拖入布局.
ImageView
被拖入布局后, UI 生成器就會立即詢問其所使用的資源(顯示在 ImageView 中的圖). constraint-layout-start
項目已經(jīng)包含了一些讓讓此 codelab 更加順利的資源. 直接去選擇 @drawable/singapore
資源就好.
選擇好后, ImageViewe
出現(xiàn)在布局上, 你可以如"約束系統(tǒng)概述"中提到的一樣點擊拖動角以調(diào)整圖片大小.
添加 TextView 到布局中
現(xiàn)在讓我們從控件板上拖一個 TextView
到布局上.
我們在 UI 生成器中看到一些警告, 這些是由 ImageView
缺失 contentDescription
參數(shù)和TextView
中硬編碼的文本導致的. 內(nèi)容描述參數(shù)(contentDescription)對構(gòu)建無障礙應用很關(guān)鍵. 在本 codelab 中, 我們使用一個預先可用的資源 @string/dummy
作為這些屬性值.
在右邊, 一個檢查面板讓你可以改變選中控件的各個參數(shù).
- 選中
ImageView
然后添加@string/dummy
到它的contentDescription
屬性中. - 在 Inspector 面板中, 還可以看見
ImageView
的其它屬性. 把scaleType
屬性改為centerCrop
以符合此 codelab 的目標. - 接下來, 我們選擇 TextView 并使用 Inspector 面板修改
text
屬性值為@string/singapore
.
此刻, 在布局中有兩個 View. 在下一節(jié), 我們會學習如何創(chuàng)建 View 之間的約束.
創(chuàng)建手工約束
要創(chuàng)建一個約束, 你需要在指定手柄上點擊并按住鼠標, 然后拖到另一個控件的約束手柄. 一旦錨點變綠, 就可以松開鼠標完成約束創(chuàng)建.
重要: UI 生成器默認自動連接(AutoConnect)模式開啟. 因為本節(jié)我們在學習手動創(chuàng)建約束, 點擊
以關(guān)閉自動連接, 或者確保它之前已經(jīng)被關(guān)閉.
在我們開始之前, 確保布局中已經(jīng)有一個 ImageView
和一個 TextView
. 這里我們的目標是創(chuàng)建已經(jīng)在布局上的 ImageView, 容器以及 TextView 之間的約束.
假定我們需要最終布局中 TextView
在 ImageView
下面. 為了實現(xiàn), 我們可以如下所示創(chuàng)建一個 TextView
上錨點和 ImageView
底錨點之間的約束.
刪除約束
使用這個
顯示在布局中的刪除約束按鈕以刪除選中控件上的 所有 約束.
要刪除單個約束, 點擊設定了該約束的錨點
如果你打算刪除布局中的所有約束, 使用菜單圖標.
下一步是創(chuàng)建 ImageView
頂錨點于 Layout 頂部的約束.
最終我們還可以使用左和右側(cè)邊約束錨定 ImageView
在布局中間.
本節(jié)演示了如何用拖拽連接線的方式創(chuàng)建控件間約束的基礎. 此時你可以通過添加其他元素的方式探索一下各種 View 和 UI 生成器. 在下一節(jié)中我們將學習Inspector.
創(chuàng)建基線約束
要連接控件的基線, 鼠標懸浮在空間上, 等幾秒鐘, 基線約束出現(xiàn)然后就可以連接了.
熟悉 Inspector
本節(jié)我們看一下 View Inspector. Inspector 在 UI 生成器上的右邊. 除了列出所選控件的屬性, 它還展示了 View 是如何對齊的以及所有的約束.
- 繼續(xù), 從布局中刪除
TextView
- 創(chuàng)建 ImageView 底錨點和容器底部的約束
UI 生成器應該看起來是這樣
Inspector 顯示出控件控件在一個方形區(qū)域的中間. 下面的小節(jié)說明了它各個元素已經(jīng)他們的使用.
Margins: 控件外部的左右上下就是 margin. 你可以點擊 margin 的值并設置成另一個值來改變它. 在上面的截圖中, margins 的值被設為 16dp.
刪除約束: 在 Inspector 中點擊鏈接控件和容器的線同樣可以刪除約束. 注意, 刪除約束刪除約束還可以通過點擊已有的約束手柄實現(xiàn).
相對約束定位控件: 當一個控件上有至少兩個對立的連接時, 比如上和下, 或者左和右, 你可以看到一個可以讓你沿著對立連接的軸調(diào)整控件位置的滑塊. 這也被稱為橫向或縱向偏量. 調(diào)整縱向和橫向偏量然后改變方向, 可以看到偏量依然保留. 另外也可以通過移動控件到目標目標位置實現(xiàn)這一點.
繼續(xù), 改變垂直偏量至75%, 而橫向偏量到75%. 下面的圖可用作參考.
控制控件的內(nèi)部尺寸: 控件內(nèi)部的線允許你控制它的尺寸, 你可以點擊特定的線看看它的具體運作方式.
這是 Inspector 中一個控件的放大視圖. 點擊 Inspector 面板控件內(nèi)部的線, 會循環(huán)切換以下選項
Fixed: 此選項允許你指定控件的高和寬.
AnySize: 此選項讓控件占用所有可用空間以適應約束. 換句話說, 這更像是匹配約束. 與 match_parent
不同, 后者占用父 View 的所有可用空間.
Wrap Content: 此選項僅擴展至所含元素(如 text 或者 drawable)填充滿 widget.
AnySize 與容器無關(guān). 如果 ImageView 約束于一個 Button, 設置為 AnySize 只會擴展它適應 button.
Figure A: 顯示 ImageView 在設定 width 為 'AnySize' 前
Figure B:顯示 ImageView 在設定 width 為 'AnySize' 后
要查看并編輯一個指定控件所有其他參數(shù), 點擊 Properties 面板右上的
在本節(jié)中, 我們探索了 Inspector. Inspector 的目的是讓你在不離開 UI 生成器的情況下編輯所有參數(shù)和約束.
使用自動連接創(chuàng)建約束
Autoconnect
, 顧名思義, 自動創(chuàng)建控件之間的連接. 理解 Autoconnect 嘗試創(chuàng)建控件與鄰近控件之間的連接的功能非常重要.
在我們開始本節(jié)前, 請確保:
- 從 Project 面板打開
res/layout/activity_main_autoconnect.xml
. 選擇 "Design" 標簽 -
Autoconnect 已經(jīng)啟用
下面我們選擇 ImageView
然后拖動它到布局中間直到提示線出現(xiàn), 幾秒鐘內(nèi), 它就被居中了, Autoconnect 介入并創(chuàng)建了與容器上下左右的約束, 如下面的動畫所示.
現(xiàn)在布局里只有單一個 ImageView
, 我們來看一下 Autoconnect 是如何創(chuàng)建約束的
這里是本節(jié)下一部分的步驟, 作為指導, 上面的動畫顯示下方使用的步驟:
- 把
ImageView
對齊到頂部并使用 Inspector(AnySize) 確保它擴展填充父 View 的寬度. - 在布局右下角放置兩個按鈕. 使用 Inspector 面板把最右邊按鈕
text
屬性改成@string/upload
, 左邊的改成@string/discard
. - 從控件板上拖一個
TextView
和一個Plain Text
到布局上. - 調(diào)整
TextView
和Plain Text
相距 48dp. 幾秒內(nèi), Autoconnect 就會創(chuàng)建兩個控件的約束. - 同樣選擇上傳按鈕并放置它接近右 margin 然后讓 Autoconnect 完成剩余的事情
- 最后把舍棄按鈕放置在距離上傳按鈕 32dp 的地方.
作為一個練習, 移動 TextView
到 ImageView
下方 48dp 的位置. 要做到這個, 選擇 TextView
并移動它直到它位于 ImageView 下方 48dp 處.
明白 Autoconnect 僅為當前正在移動的控件創(chuàng)建約束是很重要.
Autoconnect 通過自動連接相近的控件協(xié)助你, 這在很多情況下非常有用. 有些情況 Autoconnect 不能完成預期行為, 此時開發(fā)者應當使用人工約束或者推理來構(gòu)建 ConstraintLayout
. 推理將在此 codelab 的下一節(jié)討論.
使用推理創(chuàng)建約束
推理引擎輔助開發(fā)者在布局添加的元素之間創(chuàng)建約束. 由推理
創(chuàng)建的約束依賴于添加到布局的元素的類型和他們的尺寸.
推理(Inference)和自動連接(Autoconnect)有什么區(qū)別
推理引擎創(chuàng)建布局上的所有元素之間的約束, 而自動連接創(chuàng)建鄰居元素之間的約束
自動連接的目標是創(chuàng)建用來布局正在被操縱的控件的約束. 其它空間不會約束于你正在移動的控件, 但是你正在移動的控件會約束與其它控件. 這是一個重要的區(qū)別, 因為它意味著自動連接不會修改你當前的約束.
Setup
對于這一步, 我們從 layout/activity_main_inference.xml
布局開始. 在 Design 視圖中打開布局文件. 默認情況下, 此文件中的布局定義如下:
- 顯示
@drawable/singapore
和@drawable/ic_star
的ImageViews
.ic_star
圖片已經(jīng)被約束垂直偏量 81%. 你可以通過選中控件查看 Inspector 面板的方式查看包含ic_star
的ImageView
的垂直偏量, 如之前討論的一樣. - 大 ImageView (
@drawable/singapore
) 的底部錨點約束于ic_star
ImageView 的底部. -
ImageView
之外還有為ImageView
顯示相機, 設置和字幕的TextViews
.
你將要學些什么
- 使用菜單的操作橫向和縱向展開 view.
- 使用推理按鈕通過推理協(xié)助創(chuàng)建約束.
理解 UI 生成器圖標操作
由于我們將使用其中一些選項,這是一個好時機看看在UI生成器可用的操作。
刪除所有約束, 當年想以另一種方式撤銷布局中所有約束時會很有用.
使用推理創(chuàng)建約束. 推理引擎會基于諸如空間位置和大小之類的各種因素嘗試查找并創(chuàng)建最佳連接.
橫向擴展空間以適應約束
縱向擴展空間以適應約束
重要: UI 生成啟動默認啟用"自動連接". 由于本節(jié)我們打算用推理創(chuàng)建約束, 點擊
關(guān)閉自動連接.
添加一個占用可用空間的 TextView
我們的目標是是為圖片的描述添加一個 TextView. 我們已經(jīng)有一個多行的字符串資源 @string/singapore_description
.
首先, 從控件選擇板拖拽一個 TextView 并放置在設置文本下面.
-
使用
操作水平擴展 View 以適應引導線.
-
使用
操作縱向擴展以填充縱向可用空間.
使用推理操作
現(xiàn)在TextView
在布局中了, 你已經(jīng)準備好看推理的實際運作了.
點擊 infer constraints
約束引擎在布局上所有 View 之中創(chuàng)建約束. 最終的布局應該看來是這樣.
按鈕修改 "virtual device to render with". 選擇一個不同的設備, 如 Nexus 6P 或者 Nexus 9 以檢查布局渲染正確.
你現(xiàn)在已經(jīng)看到使用約束系統(tǒng)的整個系列: 創(chuàng)建手工約束, 使用自動連接約束, 還有使用推理引擎約束.
自動連接和推理通過布局引擎斷定如何為布局中各個元素創(chuàng)建約束協(xié)助你. 然后你可以進一步按照你認為合適的方式自由地修改這些約束, 無論它們是由自動連接還是推理引擎生成的.
我們討論了什么
- 創(chuàng)建手工約束
- 用自動連接創(chuàng)建約束
- 用推理創(chuàng)建約束