翻譯By Leelion6。關於 ConstraintLayout 的文章其實已經很多了,不過看到這篇文章寫的頗有趣,以及在翻譯的過程當中,感覺到了不一樣文化環境下,寫做思惟的不一樣。最關鍵的是,這篇文章的內容很細緻,對初學者比較友好,因此翻譯過來以供須要的開發者去學習。若是須要進階的用法歡迎去看郭霖等大神更深刻一些的相關文章。java
在本教程中,你將會使用
ConstraintLayout
從頭開始構建一個登陸界面,從中學習建立Android 視圖相關的基礎知識。android
做者:Fuad Kamalapp
原文連接:https://www.raywenderlich.com/9193-constraintlayout-tutorial-for-android-getting-starteddom
所需材料及源碼下載:https://koenig-media.raywenderlich.com/uploads/2019/01/RazeGalactic-1.zip編輯器
發佈日期:2019年1月30日
一款優秀的Android應用程序,須要的不只僅是美觀的UI界面,同時還要有良好的性能表現。在繪製頁面的時候,你須要把控視圖在用戶屏幕上的何處出現,以及它出現的方式。分佈式
Android提供了多種佈局類型,這些佈局中肯定子View的方式都是不一樣的。全部佈局都來自ViewGroup類。
構建Android UI經常使用的佈局有FrameLayout
, LinearLayout
和RelativeLayout
.ide
這些佈局易於使用,但當視圖結構變得複雜時,它們每一個都有其侷限性和一些性能問題:工具
FrameLayout
只能經過設置相對於父View的Gravity屬性來定位子ViewLinearLayout
不容許各View相互重疊。大多數狀況下,你必須使用多個LinearLayout
進行嵌套RelativeLayout
須要的性能較多,由於它老是會作兩次佈局測量在較新版本的Android Studio中,ConstraintLayout
已經做爲默認佈局存在了,而且提供了許多放置對象的方法:能夠相對於它們的容器自己進行約束、相對於其餘對象約束或者彼此之間進行約束、以及相對於你本身建立的guileline(輔助線)進行約束。這些方法可讓你在同一層次中建立大型、複雜、動態和響應式的視圖,甚至還能支持動畫!
佈局
您可使用該應用程序預約行星之間的旅行,計劃週末在空間站的度假,並在您抵達後預約月球車。性能
在本教程中,你將經過從頭開始構建星際旅行應用程序的登陸界面UI,以瞭解ConstraintLayout
的基本功能。
在此過程當中,你將學習:
注意:本教程假設你熟悉 Android 和 Android Studio 的基礎知識。若是你不熟悉 Android 開發,請先查看咱們的 Android入門教程 系列。
打開Android Studio 3.2.1或更高版本,經過從啓動界面選擇 Start a new Android Studio project 來建立新的Android Studio項目。
在下一個界面中,輸入 Raze Galactic 做爲 Application name (應用程序名稱)。
對於 Company domain (公司域名),你能夠輸入任意你喜歡的內容。該示例使用 raywenderlich.com 。
對於 Project location (項目位置),請選擇計算機上對你來講有意義的地址,並確保地址路徑中沒有空格。你能夠點擊項目位置字段右側的省略號 ...
以直接選擇計算機上的目錄。
最後,確保已選中 Include Kotlin support (添加Kotlin語言支持) 並點擊 Next (下一步) 按鈕。
譯者注:勾選Kotlin語言支持在本文章中並不是必要,後續的內容沒有直接使用到Kotilin,因此若是你是純粹的JAVA語言開發者或者不想使用Kotlin,這裏不勾選也徹底OK。
在接下來的界面中,進行Android設備選擇,你須要選擇 Phone and Tablet (手機和平板電腦),而後選擇 API 28: Android 9.0 (Pie) 並點擊Next。
譯者注:API部分能夠按本身習慣選擇,不必定非要到Android9.0這麼高的版本。
在「Add an Activity to Mobile」 (爲移動設備添加活動) 界面,選擇 Empty Activity (空活動)。在以後你將向這個空活動中添加UI元素,以瞭解Android中的佈局操做。
接下來———你猜對了———點擊Next!
在最後一個嚮導頁,Configure Activity(配置活動),保留全部默認配置,須要按Finish便可完成項目配置。
在開始建立新佈局以前,你須要檢查ConstraintLayout
是否須要版本更新。
你能夠在app模塊的構建Gradle文件中找到此信息。在Andoird Studio中,打開 app ▸ build.gradle 並查看其中的 dependencies { … }
部分。
在各類構建依賴項中,你應該能找到 implementation 'com.android.support.constraint:constraint-layout:x'
,其中x
是項目中ConstraintLayout
所使用的版本。
要完成本教程,你須要ConstraintLayout
1.1.3或更高版本。爲了確保你擁有最新版本的ConstraintLayout
庫,請從菜單中選擇 Tools ▸ SDK Manager 。
單擊 SDK Tools (SDK工具) 選項卡,在 Support Repository (支持的庫) 下查看 ConstraintLayout for Android ,若是顯示 installed (已安裝),則表示你使用的是最新版本
接下來,選中名爲 Show Package Details (顯示包詳情) 的複選框,以查看項目中包含的庫的版本,Gradle文件中的版本號須要與 SDK manager (SDK 管理器) 中安裝的版本相匹配。
在繼續學習本教程以前,請設置Android Studio視圖顯示方式,以便更輕鬆地添加和查看約束以及其相關元素。
首先打開 activity_main.xml ,而後單擊工具欄中的 Select Design Surface (選擇設計界面) 圖標,並選擇 Design + Blueprint (設計+藍圖)。
如今你在工做時就能看到設計預覽界面旁邊的藍圖界面了。
藍圖視圖能夠幫助你更清晰地查看約束和 guidelines (輔助線),而不會被內容或背景分散注意力。
在開發 APP UI 時,你能夠在代碼視圖 (Text tab) 和設計視圖 (Design tab) 之間來回切換。
代碼視圖容許你查看和編輯佈局背後的XML,而設計視圖對於可視化操做UI元素很是有用。設計視圖還提供了 Component Tree (組件樹) , 它能讓你查看和選擇節目中存在的全部UI元素。
當你處於代碼視圖中,可以看到視覺預覽和藍圖是頗有用的。這樣,當你在預覽界面中選擇任何元素時,XML中相應的代碼塊將變成高亮顯示。
若是你在代碼視圖中沒有看到預覽界面,請單擊右側的 Preview (預覽) 選項卡。
對於接下來的這一步,請打開 activity_main.xml 並切換到代碼視圖以查看該文件的源代碼:
<?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"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
複製代碼
請注意,此佈局的默認根元素是android.support.constraint.ConstraintLayout
。另外,帶有 「Hello World!」 文本的TextView
元素已經有了一些約束屬性,例如app:layout_constraintBottom_toBottomOf="parent"
,它的做用是將此視圖的底部約束到其父容器的底部。
在相對其父容器頂部、底部、左側還有右側都約束後,包含 「Hello World!」的 TextView
便處於了屏幕的中心。
切換到設計視圖並將鼠標光標移到包含 「Hello World!」 的TextView
上, 能夠看到有四條波浪線將TextView
鏈接到其父容器上,這些線表示TextView
已經應用了約束規則。
若是沒有出現這些線,請單擊TextView
,而後它們就會出現。若是已選中 Show Constraints (顯示約束) 視圖選項,則無需使用鼠標光標懸停或選擇任何視圖,就能夠看到全部約束。
對於下一步,你將須要在本教程開頭的應用程序屏幕截圖中看到的火箭圖像。使用教程開頭的「 下載材質」按鈕下載本教程的材料,或者點此下載。你能夠在 RazeGalactic-starter 文件夾中找到 track_icon.png 。
獲取 track_icon.png 並將其添加到項目的 drawable 文件夾中。您能夠經過在Mac上使用 command-C 或在Windows上使用 control-C 進行復制,而後右鍵單擊Android項目中的 drawable 文件夾並使用Mac上的 command-V 或Windows上的 control-V 粘貼圖像到項目中。
您能夠將UI元素從 Palette (調色板) 拖放到設計界面中。若是沒有看到 Palette ,請單擊垂直 Palette 選項卡圖標。
刪除「Hello World!」,而後將如下UI元素拖到 Palette 中的視圖中:
1個 ImageView
, 提示選擇圖像時選擇火箭圖像。
3個 Button
3個 TextView
更改UI元素的文本並將其拖動到屏幕周圍,以使它們看起來像本教程開頭的最終佈局預覽。不要過度在乎視圖的尺寸、間距或對齊的精度。
接下來,你須要添加android:textAppearance="@style/TextAppearance.AppCompat.Headline"
到 Raze Galactic TextView
以得到合適的樣式。
請注意,當你在屏幕上拖動視圖時,這些小對齊線是能幫助到你的,這些線條能夠很容易地將視圖們相互排列。
如今,構建並運行你的應用程序。
天了嚕!視圖沒有按你在設計視圖中分配好的位置排列!一切都在屏幕的左上角蜷縮着,這是腫麼回事?
嗯..好吧,Android獲得如何放置UI元素的這部分信息,由於你添加的視圖沒有任何已定義的約束。因此你須要解決這個問題。
回到Android Studio,能夠看到 Component Tree (組件樹) 中的每一個新視圖如今都有一系列錯誤。要查看錯誤的完整文本,請單擊Component Tree (組件樹)中的紅色感嘆號。
錯誤以下:
此視圖不受約束。它僅包含在剛添加時的位置,因此它會在運行時放置於(0,0)的位置,除非你添加約束。
切換回代碼視圖以檢查佈局XML的源代碼。請注意,任何視圖的源代碼都有一些帶tools
前綴的屬性,例如:
<ImageView
android:id="@+id/imageView"
android:layout_width="46dp"
android:layout_height="46dp"
app:srcCompat="@drawable/track_icon"
tools:layout_editor_absoluteX="16dp"
tools:layout_editor_absoluteY="16dp" />
複製代碼
佈局編輯器容許你將小部件放在畫布上的任何位置,並使用tools
前綴屬性記錄當前位置。這些屬性在實際運行時並不會被應用,請記住這一點。
譯者補充:
tools
前綴的屬性都是服務於佈局編輯器中的,只在XML的預覽視圖中起做用,實際運行時是沒有用的。
切換回佈局的設計視圖,你能夠在佈局預覽得上方看到一堆小控件。若是將鼠標懸停在每一個控件上,能夠閱讀該控件的簡要說明。
單擊工具欄中的磁鐵圖標以啓用 Autoconnect (自動鏈接) ,將任何視圖拖動到父視圖角落附近的區域,此時Android Studio將自動爲你建立新約束。
請注意,這僅適用於在UI元素及其父視圖之間建立約束,而不是在UI元素之間建立約束,所以 Autoconnect 的用處很是有限。大多數狀況下,你仍是關閉 Autoconnect 吧。
接下來,單擊 Infer Constraints (推測約束) 按鈕,Android Studio會自動添加布局中缺乏的約束。
再次構建並運行您的應用,會發現如今這些組件不在角落,而是出如今你放置它們的位置了。
這是添加約束的最簡單方法,但也多是最很差的。由於Android Studio佈局的意圖每每和你實際的意圖不一樣。
使用自動鏈接在特定大小的狀況下佈局多是正常的,但在不一樣的屏幕大小或屏幕方向上,可能就不會像你所但願的樣子佈局了。
若是約束混亂,你能夠清除全部約束並從頭開始從新添加約束。具體方法是,點擊 Clear All Constraints (清楚全部約束) 按鈕清除當前頁面全部約束。
Android提供了多種選項,能夠將UI元素限制在屏幕的不一樣部分,讓你靈活地設計佈局。
在本教程的這一部分中,你將學習如何將對象約束到其容器,刪除單個約束以及將對象約束到另外一個對象以達到動態佈局的效果。
請注意,當你單擊ImageView
時,它會突出顯示,而且視圖的頂部,底部,左側和右側會出現小圓圈。這些圓圈是你的約束錨點。
當你將鼠標懸停在其中一個約束錨點上時,它將閃爍綠色。Android Studio會提示你建立約束鏈接。
單擊元素左側的圓圈並將其拖動到左側。在拖動時,將出現帶箭頭的線條,在UI元素的左側和要將其鏈接到的元素之間建立約束。
將圓拖動到視圖的左側,並將圓圈ImageView
的 左側約束到父視圖的左部。對圓圈ImageView
的頂部重複此操做,將其約束到父視圖頂部。您如今已將ImageView
的約束限制在視圖的左上角。
將圖像向下拖動一點,Android Studio將在頂部建立一個邊距。經過在代碼視圖中編輯XML代碼或在設計視圖的 Attributes (屬性) 檢查器中對其進行編輯,將頂部邊距設置爲30dp。
接下來,選擇 Raze Galactic TextView
, 將左約束錨點拖動到父視圖的左側,將右約束錨點拖動到父視圖的右側。經過將此UI元素約束到左側和右側,Android明白你是想將其達到居中的效果。
接下來,將鼠標光標放在已設置約束的約束錨點之一上,表示箭頭的圓圈如今應該閃爍紅色,約束也會以紅色突出顯示。
單擊錨點就會刪除約束。如今先不要單擊,並將約束錨點保留在原位,但若是之後須要刪除約束,請記住該操做。
如今你知道如何將UI元素約束到其父容器的邊框,接下來到了學習如何將UI元素相互約束的時候了。
在本教程的這一步中,你將實現 Raze Galactic TextView
始終與火箭圖像對齊。
要作到這一點,你須要把 Raze Galactic TextView
的頂部錨點約束到ImageView
的頂部錨點,同時將TextView
底部錨點固定到ImageView
的底部錨點。兩個視圖便會垂直對齊。
如今,若是你按住火箭上下拖動,你將看到 Raze Galactic 隨着圖像上下移動。
稍後,你將看到如何使用對齊菜單建立這樣的對齊。可是,該方法並不老是天衣無縫的,因此知道如何手動完成它也是一件好事。
切換到Android Studio中的代碼視圖,並檢查剛纔添加約束的視圖的代碼:
<ImageView
android:id="@+id/imageView2"
android:layout_width="46dp"
android:layout_height="46dp"
android:layout_marginStart="16dp"
android:layout_marginTop="30dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/track_icon"/>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="Raze Galactic"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
app:layout_constraintBottom_toBottomOf="@+id/imageView2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/imageView2"/>
複製代碼
如今你已經添加了一些約束,帶有tools前綴的屬性已經消失,由於Android Studio如今再也不須要僅設計時生效的這些屬性了。
你添加的每一個約束都會在代碼中提現,好比app:layout_constraintTop_toTopOf="parent"
,表明該元素的頂部約束到了父佈局的頂部。
你能夠看到Android Studio爲你設置了一些邊距,也許你並無想過去添加。這些邊距可能看起來像android:layout_marginStart="16dp"
。
繼續往下看,在 Raze Galactic TextView
中 刪除邊距屬性後切換回設計視圖,如今你會發現, Raze Galactic TextView
應該與火箭圖像對齊了。
這兩個視圖不會再有錯誤出現了,由於已經知足了Android Studio放置這兩個UI元素所須要的信息量下限。
注意:你仍可能會看到有關使用硬編碼字符串或丟失的警告
contentDescription
。不過你如今如今能夠忽略這些。
如今,你應該將 ** Login** (登陸)按鈕與 Sign Up (註冊) 按鈕對齊,就像將 Raze Galactic TextView
與火箭圖像對齊同樣。爲此,你將須要設置三個約束:
「登陸」按鈕的頂部錨點位於「註冊」按鈕的頂部。 「登陸」按鈕的底部錨點位於「註冊」按鈕的底部。 「登陸」按鈕的左側錨點位於「註冊」按鈕的右部,並設置從左起30dp的起始邊距以在它們之間留出一些空間。
選擇 Raze Galactic TextView
並單擊右側錨點以刪除這些約束。而後,在TextView
仍然選中時,單擊工具欄中的 Align (對齊)工具,而後在選擇 Horizontally in Parent (水平佈局)。
這會自動將Raze Galactic TextView
相對父容器進行居中佈局。這與你在手動添加約束時以前實現的效果相同。
事實上,若是你切換到代碼視圖並仔細檢查Raze Galactic TextView
,你會注意到Android Studio添加了如下約束屬性:
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
複製代碼
這時你可能問了,Android Studio中自動添加的layout_constraintHorizontal_bias
是什麼?
當視圖在水平或垂直方向上受到約束時,不管是父視圖仍是其餘視圖,默認狀況下它具備0.5或50%的約束誤差。換句話說,視圖保持在它受約束的兩條邊之間的中心。
約束誤差範圍從0.0(0%)到1.0(100%),水平約束誤差從左到右增加,而垂直約束誤差從上到下增加。約束誤差對於爲不一樣的屏幕尺寸動態定位視圖頗有用。
要更輕鬆地瞭解約束誤差的工做原理,請切換回設計視圖。選中 Raze Galactic TextView
,在右側查看 view inspector (視圖查看器) 以及各類 Attributes(屬性)。
視圖查看器左側的垂直滑塊控制垂直約束誤差,底部的垂直滑塊控制水平約束誤差。拖動每一個滑塊以查看約束誤差的工做原理:
在繼續下一步以前,將水平和垂直約束的誤差重置爲50%。
接下來,同時選擇全部TextView
, Google Sign-In(從谷歌登陸) 和 Sign-Up (註冊) 按鈕。你能夠按住Shift鍵單擊每一個UI元素依次所有選中它們。而後,從工具欄中單擊 Align (對齊) 並選擇 Left Edges (左邊緣) 。
這是應用左對齊後的佈局:
你注意到這裏有什麼問題了嗎? Raze Galactic TextView
的水平約束變不見了。
左邊緣將視圖與所選擇的最左側視圖對齊,它實際上作的是按降序從一個視圖建立左約束依賴關係,以最底部的視圖充當錨點。
所以,要使 Left Edges (左邊緣)命令起做用,它必須刪除其他所選視圖的現有水平約束。
要反轉約束依賴關係順序,請再次應用 Left Edges (左邊緣)命令。您能夠看到約束箭頭如今指向上方。
如今,使用與上一步驟中選擇的相同UI元素,單擊 Pack (包) 菜單並選擇 Distribute Vertically (垂直分佈) 。
垂直分佈後,你的屏幕將以下所示:
一樣,你可能已經注意到與上述相似的問題:鏈接火箭圖標底部和 Raze Galactic TextView
的約束屬性已經消失。
約束依賴性按降序排列,就像在第一個 Left Edges (左邊緣) 命令以後同樣。不幸的是,沒有簡單的方法來解決這個問題,所以您必須手動建立垂直分佈式約束。
本教程將介紹如何在下一部分中執行此操做,所以請繼續並撤消 Distribute Vertically (垂直分佈) 命令。
注意:Align 和 Pack 命令可能沒法正常工做。它們可能會刪除現有的約束,而且可能不會移動某些受約束的視圖。在應用這些命令以前和以後,請務必檢查受影響視圖的約束。
要建立垂直分佈式約束,只需鏈接具備相同邊距的約束便可。快速完成此操做的一個技巧是使用 Default Margin (默認邊距) 工具。
如今,單擊 Default Margin (默認邊距) 按鈕並設置值爲60dp,而後將Google登陸按鈕的頂部約束鏈接到 Raze Galactic TextView
的底部。你會發現Google登陸按鈕會自動變換位置,在它與 Raze Galactic TextView
之間留出60dp的間距。 魔法 :]
建立其他的垂直約束,如上面的GIF所示。最後,將到 Raze Galactic TextView
的左側約束到火箭圖標的右側,邊距爲30dp。
檢查組件樹以查看是否存在其餘錯誤。若是沒有錯誤,恭喜!
構建並運行你的應用程序,如今全部內容應該在模擬器中以適當的佈局顯示了。
你可使用本教程頂部的下載材質按鈕下載此項目的最終版本。
ConstraintLayout
在佈局編輯器中構建UI 可能會使人沮喪,由於某些工具不夠智能。可是,若是若是你知道如何正確的去使用,則能夠節省大量時間。
本教程中未說起其餘佈局編輯器工具,你能夠去使用它們來了解它們的工做原理。看看谷歌ConstraintLayout
的文檔上,以瞭解更多信息。
有關更復雜的ConstraintLayout
示例,請參閱咱們的後續文章ConstraintLayout Android教程:複雜佈局。
要查看更多ConstraintLayout
的示例,請查看咱們的 Android Apprentice 一書,該書使用ConstraintLayout
做爲全部頁面的佈局。
你如今已經掌握了ConstraintLayout
基本的概念,要了解更多高級功能並得到處理複雜佈局的提示,請繼續關注咱們即將推出的構建複雜佈局的教程ConstraintLayout Android教程:複雜佈局,你將在其中爲 Raze Galactic 旅行應用程序構建更復雜的約束視圖,而後爲其製做動畫!
若是你有任何問題或意見,歡迎在下方留言討論~
- 李城:廣州蘆葦科技 APP 團隊 Android 開發工程師
- 咱們正在招募小夥伴,有興趣的小夥伴能夠把簡歷發到 app@talkmoney.cn,備註:來自掘金社區
- 詳情能夠戳這裏--> 廣州蘆葦信息科技