1. 程式人生 > >Constraint 程式碼實驗室--帶你一步步理解使用 ConstraintLayout

Constraint 程式碼實驗室--帶你一步步理解使用 ConstraintLayout

說明

Google I/O 2016 上釋出了 ConstraintLayout, 簡直是要變革 Android 寫介面方式. 於是第二天我立即找到相關文件嘗試, 這是官方提供的 Codelab 專案. 手把手教你探索 ConstraintLayout. 英文原文: https://codelabs.developers.google.com/codelabs/constraint-layout/index.html

本文涉及到一些詞彙對照表:

EN CN
Constraint 約束
Constraint Handle 約束手柄
AutoConnect 自動連線
Inference 推理
UI Builder UI 生成器

其中 Handle 不知如何翻譯更佳, 目前想到可供選擇的有 ‘手柄’ ‘紐’ ‘軸’ ‘操作點’ ‘操作柄’, 此文先選取最簡單的翻譯’手柄’, 如果有更好的翻譯還請賜教.

概述

在此 codelab 中, 你將會學習 ConstrainLayout – 一個構建在靈活的約束系統上的新型 Layout, 由 Android Support 庫提供. 在此 Codelab 的最後, 你將能夠使用 Android Studio 中的佈局編輯器建立一個相當複雜的佈局(使用 ConstrainLayout).

constraint-layout 庫和 UI 生成器當期處於 preview 狀態.

你將學到什麼

  • 新佈局管理器使用的約束系統
  • 建立約束以構建靈活且高效的佈局
  • 新佈局編輯器中的各種特性

你所需的準備

獲取樣例程式碼

要下載樣例程式碼, 你可以選擇:

$ git clone https://github.com/googlecodelabs/constraint-layout.git
The constraint-layout repository contains one project:

contraint-layout 倉庫包括一個工程: * constraint-layout-start — 包含此 Codelab 中你將會構建的 layout 的工程.

執行樣例程式碼

首先, 我們來看看這個已經完成的應用的樣子. 下載程式碼後, 這個指導書講解了如何用 Android Studio 開啟完整的樣例應用. 請注意此樣例需要 Android Studio 2.2 preview.

  1. 開啟 File > New > Import Project 並從之前下載樣例程式碼目錄選擇constraint-layout-start 目錄
  2. 點選Gradle sync 按鈕.
  3. 從工程面板開啟 res/layout/activity_main_done.xml.
  4. 選擇 Design 標籤檢視最終佈局.
  5. 改變 UI 生成器做上的 “Virtual Device to render the layout with(渲染所用的虛擬裝置)檢視在不同情況中的佈局.

或者:

如果你打算在 Android 裝置上執行此樣例, 開啟 MainActivity.java 並確保 setContentView 方法使用引數是activity_main_done.xml.

setContentView(R.layout.activity_main_done);

接入你的 Android 裝置並點選執行 按鈕. 你應當會看到 constraint-layout 螢幕出現在模擬器或者已連線的裝置上.

常見問題

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

約束系統概覽

佈局引擎使用每一個控制元件指定的約束確定他們在佈局中的位置. 你可以手動指定約束, 也可以使用 Android Studio 佈局編輯器推理自動指定. 為了更好的理解約束, 讓我來看看選中空間上可用的基礎手柄.

約束

約束幫助你保持控制元件對齊. 你可以使用錨點(比如下圖展示的約束手柄)來確定各控制元件之間的對齊規則. 例如, 設定一個從 button 2 的左手柄到 button 1 的右手柄的約束(見下圖A)意味著控制元件 button 2 將會位於 button 1 右邊 56dp 處.

Figure A.

手柄的型別:

Figure B. 在這個控制元件中我們可以看到不同的手柄

改變尺寸的手柄: 類似於其它你可能已經用過的繪圖設計程式, 調整尺寸的手柄允許你改變控制元件的尺寸.

側邊約束手柄: 側邊約束 handle 呈現為每一個控制元件側邊的圓圈, 可以讓你指定控制元件的位置. 例如, 你可以使用某個控制元件的左側邊約束 handle 設定控制元件總是位於另一個控制元件右邊 24dp 處. 這種手柄在此 codelab 中也被稱作錨點.

基準線約束手柄:

基準線約束 handle 幫助你對齊兩個控制元件的文字區域, 與控制元件尺寸無關. 在你想使用兩個不同大小的控制元件同時又想保持其中文字對齊的時候很有幫助.

約束系統的規則 除了以下情況外, 佈局中控制元件的錨點可以連線到其它控制元件的任意錨點. * 不同軸上的錨點, 例如左邊和上邊的錨點不能相連.
* 基線約束 handle 只能與其它極限建立約束

禁止會產生迴圈的錨點連線

構建入門專案

現在你已經準備好在入門專案上構建你的 constraint layout 了.

從左導航欄開啟 res/layout/activity_main_start.xml.

引入 constraint-layout 的依賴

constraint-layout 被構建為一個獨立的 support 庫, 支援所有 Android 2.3(Gingrebread) 以上的 Android 版本. 本入門專案已經在 app/build.gradle 中包含了它的依賴. 對於你打算用 ConstraintLayout 構建的應用, 加入如下編譯依賴:

dependencies {
  ...
  compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha'
}

定位到 res/layout/activity_main_start.xml

包含在此 codelab 專案中此 xml 佈局已經有了一個空的 ConstraintLayout 元素. ConstraintLayout一開始就被構建為在 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 專案已經包含了一些讓讓此 codelab 更加順利的資源. 直接去選擇 @drawable/singapore 資源就好.

選擇好後, ImageViewe 出現在佈局上, 你可以如”約束系統概述”中提到的一樣點選拖動角以調整圖片大小.

新增 TextView 到佈局中

現在讓我們從控制元件板上拖一個 TextView 到佈局上.

我們在 UI 生成器中看到一些警告, 這些是由 ImageView 缺失 contentDescription 引數和 TextView 中硬編碼的文字導致的. 內容描述引數(contentDescription)對構建無障礙應用很關鍵. 在本 codelab 中, 我們使用一個預先可用的資源@string/dummy 作為這些屬性值.

在右邊, 一個檢查面板讓你可以改變選中控制元件的各個引數.

  1. 選中 ImageView 然後新增 @string/dummy 到它的contentDescription 屬性中.
  2. 在 Inspector 面板中, 還可以看見 ImageView 的其它屬性. 把 scaleType 屬性改為 centerCrop 以符合此 codelab 的目標.
  3. 接下來, 我們選擇 TextView 並使用 Inspector 面板修改 text 屬性值為 @string/singapore.

此刻, 在佈局中有兩個 View. 在下一節, 我們會學習如何建立 View 之間的約束.

建立手工約束

要建立一個約束, 你需要在指定手柄上點選並按住滑鼠, 然後拖到另一個控制元件的約束手柄. 一旦錨點變綠, 就可以鬆開滑鼠完成約束建立.

重要: UI 生成器預設自動連線(AutoConnect)模式開啟. 因為本節我們在學習手動建立約束, 點選以關閉自動連線, 或者確保它之前已經被關閉.

在我們開始之前, 確保佈局中已經有一個 ImageView 和一個 TextView. 這裡我們的目標是建立已經在佈局上的 ImageView, 容器以及 TextView 之間的約束.

假定我們需要最終佈局中 TextView 在 ImageView 下面. 為了實現, 我們可以如下所示建立一個 TextView 上錨點和ImageView 底錨點之間的約束.

刪除約束

使用這個顯示在佈局中的刪除約束按鈕以刪除選中控制元件上的 所有 約束.

要刪除單個約束, 點選設定了該約束的錨點

如果你打算刪除佈局中的所有約束, 使用選單圖示.

下一步是建立 ImageView 頂錨點於 Layout 頂部的約束.

最終我們還可以使用左和右側邊約束錨定 ImageView 在佈局中間.

本節演示瞭如何用拖拽連線線的方式建立控制元件間約束的基礎. 此時你可以通過新增其他元素的方式探索一下各種 View 和 UI 生成器. 在下一節中我們將學習Inspector.

建立基線約束

要連線控制元件的基線, 滑鼠懸浮在空間上, 等幾秒鐘, 基線約束出現然後就可以連線了.

熟悉 Inspector

本節我們看一下 View Inspector. Inspector 在 UI 生成器上的右邊. 除了列出所選控制元件的屬性, 它還展示了 View 是如何對齊的以及所有的約束.

  • 繼續, 從佈局中刪除 TextView
  • 建立 ImageView 底錨點和容器底部的約束

UI 生成器應該看起來是這樣

Inspector 顯示出控制元件控制元件在一個方形區域的中間. 下面的小節說明了它各個元素已經他們的使用.

Margins: 控制元件外部的左右上下就是 margin. 你可以點選 margin 的值並設定成另一個值來改變它. 在上面的截圖中, margins 的值被設為 16dp.

刪除約束: 在 Inspector 中點選連結控制元件和容器的線同樣可以刪除約束. 注意, 刪除約束刪除約束還可以通過點選已有的約束手柄實現.

相對約束定位控制元件: 當一個控制元件上有至少兩個對立的連線時, 比如上和下, 或者左和右, 你可以看到一個可以讓你沿著對立連線的軸調整控制元件位置的滑塊. 這也被稱為橫向或縱向偏量. 調整縱向和橫向偏量然後改變方向, 可以看到偏量依然保留. 另外也可以通過移動控制元件到目標目標位置實現這一點.

繼續, 改變垂直偏量至75%, 而橫向偏量到75%. 下面的圖可用作參考.

控制控制元件的內部尺寸: 控制元件內部的線允許你控制它的尺寸, 你可以點選特定的線看看它的具體運作方式.

這是 Inspector 中一個控制元件的放大檢視. 點選 Inspector 面板控制元件內部的線, 會迴圈切換以下選項

Fixed: 此選項允許你指定控制元件的高和寬.

AnySize: 此選項讓控制元件佔用所有可用空間以適應約束. 換句話說, 這更像是匹配約束. 與 match_parent 不同, 後者佔用父 View 的所有可用空間.

Wrap Content: 此選項僅擴充套件至所含元素(如 text 或者 drawable)填充滿 widget.

AnySize 與容器無關. 如果 ImageView 約束於一個 Button, 設定為 AnySize 只會擴充套件它適應 button.

Figure A: 顯示 ImageView 在設定 width 為 ‘AnySize’ 

Figure B:顯示 ImageView 在設定 width 為 ‘AnySize’ 

要檢視並編輯一個指定控制元件所有其他引數, 點選 Properties 面板右上的

在本節中, 我們探索了 Inspector. Inspector 的目的是讓你在不離開 UI 生成器的情況下編輯所有引數和約束.

使用自動連線建立約束

Autoconnect, 顧名思義, 自動建立控制元件之間的連線. 理解 Autoconnect 嘗試建立控制元件與鄰近控制元件之間的連線的功能非常重要.

在我們開始本節前, 請確保:

  1. 從 Project 面板開啟res/layout/activity_main_autoconnect.xml. 選擇 “Design” 標籤
  2. Autoconnect 已經啟用

下面我們選擇 ImageView 然後拖動它到佈局中間直到提示線出現, 幾秒鐘內, 它就被居中了, Autoconnect 介入並建立了與容器上下左右的約束, 如下面的動畫所示.

現在佈局裡只有單一個 ImageView, 我們來看一下 Autoconnect 是如何建立約束的

這裡是本節下一部分的步驟, 作為指導, 上面的動畫顯示下方使用的步驟:

  1. 把 ImageView 對齊到頂部並使用 Inspector(AnySize) 確保它擴充套件填充父 View 的寬度.
  2. 在佈局右下角放置兩個按鈕. 使用 Inspector 面板把最右邊按鈕 text 屬性改成@string/upload, 左邊的改成@string/discard.
  3. 從控制元件板上拖一個 TextView 和一個 Plain Text 到佈局上.
  4. 調整 TextView 和 Plain Text 相距 48dp. 幾秒內, Autoconnect 就會建立兩個控制元件的約束.
  5. 同樣選擇上傳按鈕並放置它接近右 margin 然後讓 Autoconnect 完成剩餘的事情
  6. 最後把捨棄按鈕放置在距離上傳按鈕 32dp 的地方.

作為一個練習, 移動 TextView 到 ImageView 下方 48dp 的位置. 要做到這個, 選擇 TextView 並移動它直到它位於 ImageView 下方 48dp 處.

明白 Autoconnect 僅為當前正在移動的控制元件建立約束是很重要.

Autoconnect 通過自動連線相近的控制元件協助你, 這在很多情況下非常有用. 有些情況 Autoconnect 不能完成預期行為, 此時開發者應當使用人工約束或者推理來構建 ConstraintLayout. 推理將在此 codelab 的下一節討論.

使用推理建立約束

推理引擎輔助開發者在佈局新增的元素之間建立約束. 由推理建立的約束依賴於新增到佈局的元素的型別和他們的尺寸.

推理(Inference)和自動連線(Autoconnect)有什麼區別

推理引擎建立佈局上的所有元素之間的約束, 而自動連線建立鄰居元素之間的約束

自動連線的目標是建立用來佈局正在被操縱的控制元件的約束. 其它空間不會約束於你正在移動的控制元件, 但是你正在移動的控制元件會約束與其它控制元件. 這是一個重要的區別, 因為它意味著自動連線不會修改你當前的約束.

Setup

對於這一步, 我們從 layout/activity_main_inference.xml 佈局開始. 在 Design 檢視中開啟佈局檔案. 預設情況下, 此檔案中的佈局定義如下:

  • 顯示 @drawable/singapore 和 @drawable/ic_star 的 ImageViewsic_star 圖片已經被約束垂直偏量 81%. 你可以通過選中控制元件檢視 Inspector 面板的方式檢視包含ic_star 的 ImageView 的垂直偏量, 如之前討論的一樣.
  • 大 ImageView (@drawable/singapore) 的底部錨點約束於 ic_star ImageView 的底部.
  • ImageView 之外還有為ImageView 顯示相機, 設定和字幕的TextViews.

你將要學些什麼

  • 使用選單的操作橫向和縱向展開 view.
  • 使用推理按鈕通過推理協助建立約束.

理解 UI 生成器圖示操作

由於我們將使用其中一些選項,這是一個好時機看看在UI生成器可用的操作。

刪除所有約束, 當年想以另一種方式撤銷佈局中所有約束時會很有用.

使用推理建立約束. 推理引擎會基於諸如空間位置和大小之類的各種因素嘗試查詢並建立最佳連線.

橫向擴充套件空間以適應約束

縱向擴充套件空間以適應約束

重要: UI 生成啟動預設啟用”自動連線”. 由於本節我們打算用推理建立約束, 點選關閉自動連線.

新增一個佔用可用空間的 TextView

我們的目標是是為圖片的描述新增一個 TextView. 我們已經有一個多行的字串資源 @string/singapore_description.

  1. 首先, 從控制元件選擇板拖拽一個 TextView 並放置在設定文字下面.

  2. 使用操作水平擴充套件 View 以適應引導線.

  3. 使用操作縱向擴充套件以填充縱向可用空間.

使用推理操作

現在TextView 在佈局中了, 你已經準備好看推理的實際運作了.

點選 infer constraints用推理建立約束.

約束引擎在佈局上所有 View 之中建立約束. 最終的佈局應該看來是這樣.

一旦約束被建立, 你可以修改點選 UI 生成器左上的按鈕修改 “virtual device to render with”. 選擇一個不同的裝置, 如 Nexus 6P 或者 Nexus 9 以檢查佈局渲染正確.

你現在已經看到使用約束系統的整個系列: 建立手工約束, 使用自動連線約束, 還有使用推理引擎約束.

自動連線和推理通過佈局引擎斷定如何為佈局中各個元素建立約束協助你. 然後你可以進一步按照你認為合適的方式自由地修改這些約束, 無論它們是由自動連線還是推理引擎生成的.

相關推薦

Constraint 程式碼實驗室--步步理解使用 ConstraintLayout

說明 Google I/O 2016 上釋出了 ConstraintLayout, 簡直是要變革 Android 寫介面方式. 於是第二天我立即找到相關文件嘗試, 這是官方提供的 Codelab 專案. 手把手教你探索 ConstraintLayout. 英文原文:

Android LayoutInflater原理分析,步步深入瞭解View

有段時間沒寫部落格了,感覺都有些生疏了呢。最近繁忙的工作終於告一段落,又有時間寫文章了,接下來還會繼續堅持每一週篇的節奏。 有不少朋友跟我反應,都希望我可以寫一篇關於View的文章,講一講View的工作原理以及自定義View的方法。沒錯,承諾過的文章我是一定要兌現的,而且在View這個話題上我還

分鐘理解閉包--js面向物件程式設計

上一篇《簡單粗暴地理解js原型鏈--js面向物件程式設計》沒想到能攢到這麼多贊,實屬意外。分享是個好事情,尤其是分享自己的學習感悟。所以網上關於原型鏈、閉包、作用域等文章多如牛毛,很多文章寫得很深入很專業,而我卻喜歡用更簡單方式來解說簡單的事情。 什麼是閉包?  先看一段程式碼:

分鐘理解JS閉包——通俗易懂

網上關於閉包的文章有很多,但是大多數都使用了太多專業術語,不便於理解,我在這試著用通俗一點的語言解釋一下何為閉包。 什麼是閉包? 什麼是閉包?閉包是什麼? 先來看一段程式碼: function a(){ var n = 0; function inc() { n+

步步瞭解業務測打款系統的建立

1.專案背景 初始階段 業務方訂單稽核通過後,會有離線任務不斷輪訓向支付中心發起呼叫,支付中心打款處理完成後會返回ifSuccess(是否落庫),state,code,error Message等。如果落庫且code為打款成功,訂單業務狀態會修改為打款成功。 發展階段 為了配合業務發展,會增加各種活動來拉動訂

Android檢視繪製流程完全解析,步步深入瞭解View(二)

在上一篇文章中,我帶著大家一起剖析了一下LayoutInflater的工作原理,可以算是對View進行深入瞭解的第一步吧。那麼本篇文章中,我們將繼續對View進行深入探究,看一看它的繪製流程到底是什麼樣的。如果你還沒有看過我的上一篇文章,可以先去閱讀 Android Layo

Android自定義View的實現方法,步步深入瞭解View(四)

不知不覺中,帶你一步步深入瞭解View系列的文章已經寫到第四篇了,回顧一下,我們一共學習了LayoutInflater的原理分析、檢視的繪製流程、檢視的狀態及重繪等知識,算是把View中很多重要的知識點都涉及到了。如果你還沒有看過我前面的幾篇文章,建議先去閱讀一下,多瞭解一些

Android自定義View的實現方法 步步深入瞭解View 四

                不知不覺中,帶你一步步深入瞭解View系列的文章已經寫到第四篇了,回顧一下,我們一共學習了LayoutInflater的原理分析、檢視的繪製流程、檢視的狀態及重繪等知識,算是把View中很多重要的知識點都涉及到了。如果你還沒有看過我前面的幾篇文章,建議先去閱讀一下,多瞭解一些原

Android LayoutInflater原理分析,步步深入瞭解View()

有段時間沒寫部落格了,感覺都有些生疏了呢。最近繁忙的工作終於告一段落,又有時間寫文章了,接下來還會繼續堅持每一週篇的節奏。有不少朋友跟我反應,都希望我可以寫一篇關於View的文章,講一講View的工作原理以及自定義View的方法。沒錯,承諾過的文章我是一定要兌現的,而且在Vi

Android檢視狀態及重繪流程分析,步步深入瞭解View(三)

在前面一篇文章中,我帶著大家一起從原始碼的層面上分析了檢視的繪製流程,瞭解了檢視繪製流程中onMeasure、onLayout、onDraw這三個最重要步驟的工作原理,那麼今天我們將繼續對View進行深入探究,學習一下檢視狀態以及重繪方面的知識。如果你還沒有看過我前面一篇文章

iOS元件化-步步實現專案的元件化

元件化在業界已經炒的水深火熱,關於元件化的好處和元件化的方案網上已經有大篇的文章了。筆者通過拆分一個現有的demo來簡單聊一下專案實施元件化的過程(將分為上、中、下三篇)。demo可以從github下

Android冷啟動白屏解析,步步分析和解決問題

本文同步發表於我的微信公眾號,掃一掃文章底部的二維碼或在微信搜尋 郭霖 即可關注,每天都有文章更新。 寫在前面 記得在本月初,我發表了一篇文章叫《 Android Studio新功能解析,你真的瞭解Instant Run嗎?》,裡面詳細講解了

步步實現帶有多彩陰影的ImageView

身為android開發者,ImageView那一定是玩的滾瓜爛熟,現在如今Material Design設計也越來越流行,給ImageView實現陰影也不是什麼難事,用CardView包裹一下,就能實現了,但是陰影都是一種顏色,實在太單調了╮(╯▽╰)╭,我就在

我是這樣步步理解--主題模型(Topic Model)、LDA(案例程式碼)

1. LDA模型是什麼 LDA可以分為以下5個步驟: 一個函式:gamma函式。 四個分佈:二項分佈、多項分佈、beta分佈、Dirichlet分佈。 一個概念和一個理念:共軛先驗和貝葉斯框架。 兩個模型:pLSA、LDA。 一個取樣:Gibbs取樣 關於LDA有兩種含義,一種是線性判別分析(Linear

Python難嗎?華為雲學院探究竟!

數據 對比 pac 常用 靜態 必須 面向對象 如何 開源 Python是一直廣受大家歡迎的編程語言,簡單易學並且功能非常強大。python擁有高效的高級數據結構,並且能夠簡單並且快速的進行面向對象的編程。python的語法簡潔優雅,並且它是動態語言,加上它的語言的可解釋性

深入python協程的實現,層揭開協程的神祕面紗!

協程與 子例程一樣,協程(coroutine)也是一種程式元件。相對子例程而言,協程更為一般和靈活,但在實踐中使用沒有子例程那樣廣泛。協程源自 Simula 和 Modula-2 語言,但也有其他語言支援。 看完之後,我的表情是這樣的: 用專業詞彙解釋專業詞彙,相當於沒說

Jquery 分頁外掛, 步接入後臺資料

目錄   一、效果圖 二、分頁 js 原始碼講解 三、分頁樣式 css 原始碼 三、實現前後臺對接 一、效果圖 二、分頁 js 原始碼講解 新建一個 js 檔案,基本直接複製貼上就行,記得引入到需要的頁面中。 需要注意的是: 前面的建構函式

圖解CNN 通過100張圖步步理解CNN

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

2 張圖,讓理解 CountDownLatch、CyclicBarrier

CountDownLatch (倒數閂,Latch:門閂) 經常用於 監聽某些初始化操作,等 初始化執行緒 全部執行完畢後,才通知 主執行緒 繼續工作 a) 即 一個執行緒處於阻塞的狀態下,他要收到 多少次通知,才能被 甦醒,並繼續往下執行 b) 注意:只能阻塞 一個執行

JAVA步實現微信公眾號開發()--接入微信公眾平臺

(一)接入流程解析 在我們的開發過程中無論如何最好的參考工具當然是我們的官方文件了:http://mp.weixin.qq.com/wiki/8/f9a0b8382e0b77d87b3bcc1ce6fbc104.html 通過上面我們可以看出其中接入微信公眾平臺開發,開發者需要按照如下