1. 程式人生 > >1.2 快速掌握 Android 中的六大布局

1.2 快速掌握 Android 中的六大布局

本篇我們介紹了六大布局* Linear Layout(線性佈局)、Frame Layout(幀佈局)、Relative Layout(相對佈局)、Absolute Layout(絕對佈局)、Table Layout(表格佈局)、Absolute Layout(絕對佈局) *的常用屬性,然後結合實際開發中遇到的各種場景給出了相應的解決方案和示例用法,並且結合不同佈局的各自特點給出了自身特有的屬性(重複的屬性不會列出),方便大家在後續學習UI排布的課程中進行查閱。最後,給出了 Android 中佈局優化的一些建議。

佈局是一種可用於放置很多控制元件的容器,它可以按照一定的規律調整內部控制元件的位置,從而編寫出精美的介面。當然了,佈局的內部除了放置控制元件外, 也可以放置佈局,通過多層佈局的巢狀,我們就能夠完成一些比較複雜的介面實現。

Layout

為了更好地管理Android應用的使用者介面裡的個元件,Android提供了佈局管理器,通過佈局管理器,Android應用的圖形使用者介面就具有了良好的平臺無關性。這就讓各個控制元件都可以有條不紊地擺放在介面上,而不是亂糟糟的。

LinearLayout是一種非常常用的佈局,正如它名字所描述的一樣,這個佈局會將它所包含的控制元件線上性方向上依次排列,當然肯定就不僅只有一個方向,我們可以通過 android:orientation 這個屬性指定排列方向是 vertical 還是 horizontal,控制元件就會在豎直方向上或者水平方向上進行排列。

下面我們通過例項來體會一下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity= "right|center_vertical">
<Button
    android:id="@+id/bn1"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/bn1"/>
<Button android:id="@+id/bn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/bn2"/> <Button android:id="@+id/bn3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/bn3"/> <Button android:id="@+id/bn4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/bn4"/> <Button android:id="@+id/bn5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/bn5"/> </LinearLayout>

上面的佈局介面很簡單,只是很簡單的定義了一個線性佈局,在佈局中定義了五個按鈕並制定了屬性“android:gravity = “right | center_vertical””,實際執行效果如下:
LinearLayout效果一

如果將上面的屬性改為“android:gravity = “bottom | center_horizontal””,那麼實際執行效果為:
LinearLayout效果二

也就是說在垂直佈局的前提下底部居中、水平居中,就變成了這個樣子,可以看到屬性對區域性的影響是很大的。

下面列出LinearLayout常用的屬性:

android:layout_gravity: 本元素相對於父元素的重力方向
android:layout_weight:子元素對未佔用空間水平或垂直分配權重值
android:gravity[setGravity(int)] :本元素所有子元素的重力方向
android:orientation[setOrientation(int)]:線性佈局以列或行來顯示內部子元素
android:divider[setDividerDrawable(Drawable)]:設定垂直佈局時兩個控制元件之間的分隔條
android:baselineAligned[setBaselineAligned(boolean)]:該屬性為false,將會阻止該佈局管理器與它的子元素的基線對齊
android:measureWithLargestChild[setMeasureWithLargestChildEnabled(boolean)]當該屬性設定為true時,所有帶權重的子元素都會具有最大子元素的最小尺寸

問1:android:layout_gravity 和 android:gravity 有什麼區別?

  • android:gravity:對元素本身起作用-本身元素顯示在什麼位置
  • android:layout_gravity:相對與它的父元素-元素顯示在父元素的什麼位置

* 如:Button控制元件 *
- android:layout_gravity 表示button在介面上的位置
- android:gravity 表示button上的字在button上的位置

問2:受控子元素如何設定?

LinearLayout的所有子元素都受 LinearLayout.LayoutParams 的控制,因此 Linear Layout 包含的子元素可以額外指定以下屬性:

  • android:layout_gravity 子元素在LinearLayout中的對齊方式
  • android:layout_weight 子元素在LinearLayout中所佔的權重

所以我們要實現第一個的 1:2 的效果,只需要分別把兩個 Linear Layout 的 weight 分別設定成1和2就可以了。

比如將上述佈局程式碼改為如下方式:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:background="#2fc1ff"
        android:layout_weight="1"/>
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:background="#f7242b"
        android:layout_weight="2"/>
</LinearLayout>
那麼實際的執行效果為:

權重分配效果

用法歸納:

按比例劃分水平方向,將涉及到的 View 的 android:width 屬性設定為 0dp,然後設定為 android weight 屬性設定比例即可;類推豎直方向,只需設 android:height 為 0dp,然後設 weight 屬性即可!

RelativeLayout 也是一種非常常用的佈局,和 LinearLayout 的排列規則不同的是, RelativeLayout 顯得更加隨意一些,它總是通過相對定位的方式讓控制元件出現在佈局的任何位置,比如說相對容器內兄弟元件、父容器的位置決定了它自身的位置。也正因為如此, RelativeLayout 中的屬性非常多,不過這些屬性都是有規律可循的。

實現一個梅花布局效果:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    <!-- 定義該元件位於父容器中間 -->
    <TextView
        android:id="@+id/view01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/leaf"
        android:layout_centerInParent="true"/>
    <!-- 定義該元件位於view01元件的上方 -->
    <TextView
        android:id="@+id/view02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/leaf"
        android:layout_above="@id/view01"
        android:layout_alignLeft="@id/view01"/>
    <!-- 定義該元件位於view01元件的下方 -->
    <TextView
        android:id="@+id/view03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/leaf"
        android:layout_below="@id/view01"
        android:layout_alignLeft="@id/view01"/>
    <!-- 定義該元件位於view01元件的左邊 -->
    <TextView
        android:id="@+id/view04"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/leaf"
        android:layout_toLeftOf="@id/view01"
        android:layout_alignTop="@id/view01"/>
    <!-- 定義該元件位於view01元件的右邊 -->
    <TextView
        android:id="@+id/view05"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/leaf"
        android:layout_toRightOf="@id/view01"
        android:layout_alignTop="@id/view01"/>
</RelativeLayout>
執行效果如下:

RelativeLayout 梅花布局效果

程式碼稍微複雜一點,不過難以理解的也就兩個屬性,一個是 android:layout_toxxxOf,這個是一個控制元件位於另一個控制元件上下左右的相對位置,另一個是android:layout_alignxxx,表示一個控制元件與另一個控制元件對齊,這裡我們列出更詳細的屬性規則:

相對位置規則:
android:layout_above 將該控制元件的底部至於給定ID的控制元件之上
android:layout_below 將該控制元件的頂部至於給定ID的控制元件之下
android:layout_toLeftOf 將該控制元件的右邊緣和給定ID的控制元件的左邊緣對齊
android:layout_toRightOf 將該控制元件的左邊緣和給定ID的控制元件的右邊緣對齊
兄弟控制元件對齊規則:
android:layout_alignBaseline 將該控制元件的baseline和給定ID的控制元件的baseline對齊
android:layout_alignBottom 將該控制元件的底部邊緣與給定ID控制元件的底部邊緣對其
android:layout_alignTop 將給定控制元件的頂部邊緣與給定ID控制元件的頂部對齊
android:layout_alignLeft 將該控制元件的左邊緣與給定ID控制元件的左邊緣對齊
android:layout_alignRight 將該控制元件的右邊緣與給定ID控制元件的右邊緣對齊
父控制元件對齊規則:
android:alignParentBottom 如果該值為true,則將該控制元件的底部和父控制元件的底部對齊
android:layout_alignParentLeft 如果該值為true,則將該控制元件的左邊與父控制元件的左邊對齊
android:layout_alignParentRight 如果該值為true,則將該控制元件的右邊與父控制元件的右邊對齊
android:layout_alignParentTop 如果該值為true,則將空間的頂部與父控制元件的頂部對齊
中央位置規則:
android:layout_centerVertical 如果值為真,該控制元件將被至於垂直方向的中央
android:layout_centerHorizontal 如果值為真,該控制元件將被至於水平方向的中央
android:layout_centerInParent 如果值為真,該控制元件將被至於父控制元件水平方向和垂直方向的中央
重力規則:
android:gravity[setGravity(int)]設定容器內各個子元件的重力方向
android:ignoreGravity[setIgnoreGravity(int)]設定容器哪個子元件的不受重力方向影響

Frame Layout 相比於前面兩種佈局就簡單多了,你可能因此就覺得它的應用場景會少很多,不過也要看情況,如果是應用在比較複雜的自定義佈局的時候,那麼幀佈局還是很受歡迎的,因為這種佈局沒有任何的定位方式,所有的控制元件都會擺放在佈局的左上角,不像其它佈局那樣充滿了各種各樣的規則。當你翻開幀佈局的原始碼的時候也會驚奇的發現相比於其它佈局它的程式碼量要少很多,這就導致了在複雜的自定義佈局控制元件中選用幀佈局作為父類的話就會一定程度上提升UI的渲染的效能。

實現一個疊加效果:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="match_parent">
    <!-- 依次定義6個TextView,先定義的TextView位於底層,後定義的TextView位於上層 -->
    <TextView
        android:id="@+id/view01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="160pt"
        android:height="160pt"
        android:background="#f00"/>
    <TextView
        android:id="@+id/view02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="140pt"
        android:height="140pt"
        android:background="#0f0"/>
    <TextView
        android:id="@+id/view03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="120pt"
        android:height="120pt"
        android:background="#00f"/>
    <TextView
        android:id="@+id/view04"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="100pt"
        android:height="100pt"
        android:background="#ff0"/>
    <TextView
        android:id="@+id/view05"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="80pt"
        android:height="80pt"
        android:background="#f0f"/>
    <TextView
        android:id="@+id/view06"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="60pt"
        android:height="60pt"
        android:background="#0ff"/>
</FrameLayout>

執行起來的效果是:
FrameLayout 佈局效果

幀佈局容器為每個加入其中的元件建立一個空白的區域(即一幀),每個子元件佔據一幀,這些幀都會根據gracity屬性自動對齊並按照新增的順序先後疊加在一起。

FrameLayout的一些屬性:
android:foreground[setForeground(Drawable)] 定義幀佈局容器的繪圖前景影象
android:foregroundGravity[setForegroundGravity(int)] 定義繪圖前景影象的重力屬性

Table Layout 允許我們使用表格的方式來排列控制元件。既然是表格,那就一定會有行和列,在設計表格時我們儘量應該讓每一行都擁有相同的列數,這樣的表格也是最簡單的。不過有時候事情並非總會順從我們的心意,當表格的某行一定要有不相等的列數時, 就需要通過合併單元格的方式來應對。

下面的例子示範瞭如何用 Table Layout 來管理佈局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#3354fc"/>

    <!-- 定義第一個表格佈局,指定第2列允許收縮,第3列允許拉伸 -->
    <TableLayout android:id="@+id/TableLayout01"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:shrinkColumns="1"
        android:stretchColumns="2">
        <!-- 直接新增按鈕,它自己會佔一行 -->
        <Button android:id="@+id/ok1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="獨自一行的按鈕"/>
        <!-- 新增一個表格行 -->
        <TableRow>
            <!-- 為該表格行新增三個按鈕 -->
            <Button android:id="@+id/ok2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="普通的一個按鈕"/>
            <Button android:id="@+id/ok3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="收縮按鈕"/>
            <Button android:id="@+id/ok4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="拉伸按鈕"/>
        </TableRow>
    </TableLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#3354fc"/>

    <!-- 定義第2個表格佈局 ,指定第2列隱藏-->
    <TableLayout android:id="@+id/TableLayout02"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:collapseColumns="1">
        <!-- 直接新增按鈕,它自己會佔一行 -->
        <Button android:id="@+id/ok5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="獨自一行的按鈕"/>
        <!-- 新增一個表格行 -->
        <TableRow>
            <!-- 為該表格行新增三個按鈕 -->
            <Button android:id="@+id/ok6"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="普通按鈕1"/>
            <Button android:id="@+id/ok7"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="普通按鈕2"/>
            <Button android:id="@+id/ok8"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="普通按鈕3"/>
        </TableRow>
    </TableLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#3354fc"/>

    <!-- 定義第3個表格佈局,指定第2列和第3列可以被拉伸-->
    <TableLayout
        android:id="@+id/TableLayout03"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:stretchColumns="1,2">
        <!-- 直接新增按鈕,它自己會佔一行 -->
        <Button
            android:id="@+id/ok9"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="獨自一行的按鈕"
            />
        <!--定義一個表格行-->
        <TableRow>
        <!-- 為該表格行新增三個按鈕 -->
        <Button
            android:id="@+id/ok10"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="普通按鈕"
            />
        <Button
            android:id="@+id/ok11"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="拉伸的按鈕"
            />
        <Button
            android:id="@+id/ok12"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="拉伸的按鈕"
            />
        </TableRow>
        <!--定義一個表格行-->
        <TableRow>
            <!-- 為該表格行新增兩個按鈕 -->
            <Button
                android:id="@+id/ok13"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="普通按鈕"
                />
            <Button
                android:id="@+id/ok14"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="拉伸的按鈕"
                />
        </TableRow>
    </TableLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#3354fc"/>
</LinearLayout>
上面定義了三個 Table Layout ,通過 TextView 分割開來並通過程式碼指定了它們對各自列的控制行為:
  • 第一個TableLayout :指定第2列允許收縮,第3列允許拉伸
  • 第二個TableLayout :指定第2列隱藏
  • 第三個TableLayout :指定第2列和第3列可以被拉伸

並且上面的每個按鈕寬度所用的屬性都是 android:layout_width=”wrap_content” ,正常來講按鈕只要包裹住美容即可,但是因為我們指定了相應列的屬性,那麼可以看到執行的效果如下:
TableLayout 佈局效果

相關的屬性:
android:collapseColumns[setColumnCollapsed(int,boolean)] 設定需要被藏的列的列號,多個列號之間用逗號隔開
android:shrinkColumns[setShrinkAllColumns(boolean)] 設定允許被收縮的列的列號,多個列號之間用逗號隔開
android:stretchColumns[setStretchAllColumns(boolean)] 設定允許被拉伸的列的列號,多個列號之間用逗號隔開

GridLayout是Android4.0之後新增的佈局管理器,因此正常情況下需要在 Android 4.0 之後的版本中才能使用,如果希望在更早的版本中使用的話,需要匯入相應的支撐庫(v7包的gridlayout包)。

Grid Layout 和前面所講的 Table Layout(表格佈局) 有點類似,不過他有很多前者沒有的東西,因此也更加好用:
- 可以自己設定佈局中元件的排列方式
- 可以自定義網格佈局有多少行、列
- 可以直接設定元件位於某行某列
- 可以設定元件橫跨幾行或者幾列

實現一個計算器介面:

<?xml version="1.0" encoding="utf-8" ?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:rowCount="6"
            android:columnCount="4"
            android:id="@+id/root">
    <!-- 定義一個橫跨4列的文字框,並設定該文字框的前景色、背景色等屬性  -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_columnSpan="4"
        android:textSize="50sp"
        android:layout_marginLeft="2pt"
        android:layout_marginRight="2pt"
        android:padding="3pt"
        android:layout_gravity="right"
        android:background="#eee"
        android:textColor="#000"
        android:text="0"/>
    <!-- 定義一個橫跨4列的按鈕 -->
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_columnSpan="4"
        android:text="清除"/>
</GridLayout>

首先在佈局檔案中定義了一個 6*4 的 Grid Layout,然後在該佈局中新增兩個元件並且每個元件均橫跨4列,接下來在Java中動態新增16個按鈕:

public class MainActivity extends Activity
{
    GridLayout gridLayout;
    // 定義16個按鈕的文字
    String[] chars = new String[] {
                    "7" , "8" , "9" , "÷",
                    "4" , "5" , "6" , "×",
                    "1" , "2" , "3" , "-",
                    "." , "0" , "=" , "+"
            };
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        gridLayout = (GridLayout) findViewById(R.id.root);
        for(int i = 0 ; i < chars.length ; i++)
        {
            Button bn = new Button(this);
            bn.setText(chars[i]);
            // 設定該按鈕的字號大小
            bn.setTextSize(40);
            // 設定按鈕四周的空白區域
            bn.setPadding(5 , 35 , 5 , 35);
            // 指定該元件所在的行
            GridLayout.Spec rowSpec = GridLayout.spec(i / 4 + 2);
            // 指定該元件所在的列
            GridLayout.Spec columnSpec = GridLayout.spec(i % 4);
            GridLayout.LayoutParams params = new GridLayout.LayoutParams(
                    rowSpec , columnSpec);
            // 指定該元件佔滿父容器
            params.setGravity(Gravity.FILL);
            gridLayout.addView(bn , params);
        }
    }
}

Java類中採用迴圈的方式向 Grid Layout 中添加了16個按鈕,指定了每個按鈕所在的行號和列號,並指定這些按鈕會自動填充單元格的所有空間——避免了單元格中的大量空白,執行效果如下:
Grid Layout 佈局效果

以下為GridLayout常用屬性:

排列對齊:
- 設定元件的排列方式: android:orientation=”” vertical(豎直,預設)或者horizontal(水平)
- 設定元件的對齊方式: android:layout_gravity=”“[setGravity(int)] center,left,right,buttom,如果想同時用兩種的話:buttom|left
設定佈局為幾行幾列:
- 設定有多少行:android:rowCount=”4”[setrowCount(int)] //設定網格佈局有4行
- 設定有多少列:android:columnCount=”4”[setColumnCount(int)] //設定網格佈局有4列

設定某個元件位於幾行幾列:
- 元件在第幾行:android:layout_row = “1” //設定元件位於第二行
- 元件在第幾列:android:layout_column = “2” //設定該元件位於第三列
設定某個元件橫跨幾行幾列:
- 橫跨幾行:android:layout_rowSpan = “2” //縱向橫跨2行
- 橫跨幾列:android:layout_columnSpan = “3” //橫向橫跨2列

其他設定:
- 佈局管理器採用的對齊方式:android:alignmentMode[setAlignmentMode(int)]
- 佈局管理器是否保留列序號:android:columnOrderPreserved[setColumnOrderPreserved(boolean)]
- 佈局管理器是否保留行序號:android:rowOrderPreserved[setRowOrderPreserved(boolean)]
- 佈局管理器是否使用預設的頁邊距:android:useDefaultMargins[setUseDefaultMargins(boolean)]

Absolute Layout 就像它名字所展現的那樣,它不提供任何佈局控制,而是由開發人員自己通過X、Y座標來控制組件的位置。所以絕大多數情況下我們是不採用絕對佈局這種佈局方式的,因為執行Android應用的手機往往千差萬別,螢幕大小、分別率、螢幕密度等都可能存在較大的差異,使用絕對佈局的話很難做機型適配,因此我們瞭解這種佈局方式即可。

先了解下程式碼:

<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- 定義一個文字框,使用絕對定位 -->
    <TextView
        android:layout_x="20dp"
        android:layout_y="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="使用者名稱:"/>
    <!-- 定義一個文字編輯框,使用絕對定位 -->
    <EditText
        android:layout_x="80dp"
        android:layout_y="15dp"
        android:layout_width="wrap_content"
        android:width="250dp"
        android:layout_height="wrap_content" />
    <!-- 定義一個文字框,使用絕對定位 -->
    <TextView
        android:layout_x="20dp"
        android:layout_y="80dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="密  碼:"/>
    <!-- 定義一個文字編輯框,使用絕對定位 -->
    <EditText
        android:layout_x="80dp"
        android:layout_y="75dp"
        android:layout_width="wrap_content"
        android:width="250dp"
        android:layout_height="wrap_content"
        android:password="true"/>
    <!-- 定義一個按鈕,使用絕對定位 -->
    <Button
        android:layout_x="130dp"
        android:layout_y="135dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登   錄"/>
</AbsoluteLayout>

使用絕對佈局需要像上面這樣給每個子元件都指定 android:layout_x、android:layout_y 兩個定位屬性,這樣才控制得了每個子元件在容器中出現的位置,執行得到的效果如下:
Absolute Layout 佈局效果

實際上想要通過絕對佈局達到以上的效果需要反覆多次執行比對,很顯然這樣的程式設計方式要繁瑣的多,而且在不同螢幕上的顯示效果差異巨大,這裡給出Android中常用的距離單位:

px(畫素):每個對應螢幕上的一個點
dip或dp(device independent pixels,裝置獨立畫素):一種基於螢幕密度的抽象單位,在每英寸160點的顯示器上,1dip=1px
sp(scaled pixels,比例畫素):主要處理字型的大小,可以根據字型大小首選項進行縮放
in(英寸):標準長度單位

1、儘可能減少佈局的巢狀層級

可以使用 sdk 提供的 hierarchyviewer 工具分析檢視樹,幫助我們發現沒有用到的佈局。

2、不用設定不必要的背景,避免過度繪製

比如父控制元件設定了背景色,子控制元件完全將父控制元件給覆蓋的情況下,那麼父控制元件就沒有必要設定背景。

3、使用標籤複用相同的佈局程式碼

4、使用標籤減少檢視層次結構

該標籤主要有兩種用法:

1) 因 為 所 有 的 Activity 視 圖 的 根 節 點 都 是 Frame Layout , 因 此 如 果 我 們 的 自 定 義 的 布 局 也 是 Fragmen Layout 的時候那麼可以使用 merge 替換。
2) 當應用 Include 或者 View Stub 標籤從外部匯入 xml 結構時,可以將被匯入的 xml 用 merge 作為根節點表示,這樣當被嵌入父級結構中後可以很好的將它所包含的子集融合到父級結構中,而不會出現冗餘的節點。
只能作為 xml 佈局的根元素。

5、通過實現 View 的延遲載入

佈局如下:
<ViewStub
android:id="@+id/vs"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:inflatedId="@+id/my_view"
android:layout="@layout/my_layout" />
Java核心程式碼:
public void loadVS(View view){
ViewStub vs = (ViewStub) findViewById(R.id.vs);
View inflate = vs.inflate();
int inflatedId = vs.getInflatedId();
int id = inflate.getId();
Toast.makeText(this, "inflatedId="+inflatedId+"***"+"id="+id,
Toast.LENGTH_SHORT).show();

點選關注,第一時間獲得後續文章。

微信公眾號:WillFlow