前幾天介紹了好幾種UI基礎元件,你已經知道怎麼畫這些東西了,那該把他們畫在哪裡咧?
該是介紹 layout 出場的時候了
前幾天介紹的 TextView、ImageView、EditText...等等,都是 View 類別的直接或間接子類別。
ViewGroup 是一抽象類別,顧名思義就是裝載這些 Views 或其他 ViewGroup 的隱形容器,雖不可見,卻影響著裡頭所有元件的版面配置(佈局),ViewGroup 是各式各樣的 layouts 和 views containers 的父類別(也稱超類、基類),UI 版面配置的方式都是由 layout定義。
layout 與裡面嵌著的元件(可能是 TextView、Button 等元件或另一個 layout)存在著階層關係。外層是父,中間夾著的 views 或其他ViewGroup 就是孩子。不會出現你的孩子不是你的孩子的問題。
Layout版面配置官方文檔
Android 提供了許多種不同的 layouts,而這些 layouts 對於元件都有各自擺放規則,讓我們可以依照需求靈活地完成各種構圖,而對用戶來說,並無法看見這個畫面使用了那些 layouts。這蠻好理解,每對父母都會有不同的養育規則,無形中影響著自己的孩子。layout有很多種,底下介紹比較常用到的 FrameLayout、 LinearLayout、ConstraintLayout。
FrameLayout(禎佈局)是一種簡單好理解的 layout,單純將元件對齊 layout 左上角疊起,若裡面元件尺寸相同,那只會看到最頂層的元件。並且元件只能以 layout_gravity 來定義位置。
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="48dp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#74FFFFFF"
android:text="button"
android:textColor="@color/teal_200"
android:textSize="48sp"
android:layout_gravity="center"/>
<ImageButton
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="bottom|center"
android:contentDescription="@string/image_description"
android:src="@drawable/child_face"/>
<ImageView
android:id="@+id/rabbit"
android:layout_width="400dp"
android:layout_height="500dp"
android:background="#F0F4C0"
android:src="@drawable/rabbit"
android:contentDescription="@string/image_description"/>
</FrameLayout>
註:stateListAnimator是可以讓View隨著狀態動起來的屬性。用法參考這篇有範例
運行模擬機時,使用 Layout Inspector 來做檢視,滑桿可控制圖層間距,使其更方便檢視。
LinearLayout(線性佈局)對我來說,就像軍事化教育的父母,子元件都必須依照他指定的水平或垂直的方向進行排列,並且不可重疊。
排列的方向則由orientation屬性決定,這個屬性會影響所有放在裡面的子元件。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="horizontal"
android:background="@color/teal_200"
tools:context="com.tseng.theironmandemo.MainActivity2">
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_margin="4dp"
android:src="@drawable/child_face" />
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_margin="4dp"
android:background="#FFEB3B"
android:src="@drawable/child_face" />
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_margin="4dp"
android:background="#FFEB3B"
android:src="@drawable/child_face" />
</LinearLayout>
如果堅持都用LinearLayout做出格狀配置,就需要一行行或一列列嵌套。
不同底色是不同LinearLayout,上圖用了5個。官方不建議這樣處理,層層嵌套會影響介面效能。
ConstraintLayout(約束佈局)就是放牛吃草的父母。
他也是預設的 layout,元件只需要1條水平約束線 + 1條垂直的約束線定位,可以很自由跟父層或附近的其他子元件約定好位置,可以用來繪製比較豐富複雜需要高自由度的排版,才不會layouts 一層嵌一層,而造成文件很複雜也可能影響繪製速度。
現在將編輯模式切到 Design 模式檢視,視窗主要分成三大塊
我覺得雖然ConstraintLayout也是以XML的型式來儲存,但是它又與其他的 layout 又有些區別,因為單純用程式碼模式編輯的話會覺得很麻煩,ConstraintLayout比較適合用Design模式來放定位拉好約束後,細節再用code來微調會比較省事。
官方文檔:
ConstraintLayout
Build a Responsive UI with ConstraintLayout
雖然XML的結構可以像俄羅斯娃娃多層嵌套下去,但是基於優化效能,官方文件建議,還是要以最簡單階層完成需求為目標,這樣繪製的速度才會快起來~
官方文檔 :
Optimizing layout hierarchies
效能與檢視區塊階層
既然是新手友善系列,介紹一下工具列是需要的吧。
上排是通用的工具列,但 layout 不同,下排工具也會不同。
ConstraintLayout的下排工具比較複雜,用它當範本(下圖)
明天再更詳細一點介紹ConstraintLayout,打家明天見~