1. 程式人生 > >【Android】Android六種布局詳解

【Android】Android六種布局詳解

spec rec 默認 bottom ron ado 居中 右下角 控制

這篇就對LinearLayout、RelativeLayout、自定義ViewGroup、FrameLayout、TableLayout、AbsoluteLayout六種布局進行詳細的講解。

技術分享

1.LinearLayout布局

線性布局,兩種排法:

  • 從左到右
    android:orientation=”horizontal”
  • 從上到下
    android:orientation=”vertical”
    具體上圖

技術分享
一個豎向的大LinearLayout嵌套著兩個小LinearLayout,第一個小LinearLayout為橫向,第二個小LinearLayout為豎向。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"    
    android:layout_width="match_parent"    
    android:layout_height="match_parent"    
    android:orientation="vertical">    
<LinearLayout        
    android:layout_width="match_parent"        
    android:layout_height="250dp"        
    android:orientation="horizontal">        
    <TextView           
        android:layout_width="96dp"      
        android:layout_height="match_parent" 
        android:background="#b2dfdb" />        
    <TextView            
        android:layout_width="96dp"               
        android:layout_height="match_parent"             
        android:background="#80cbc4" />       
     <TextView            
        android:layout_width="96dp"                   
        android:layout_height="match_parent"            
        android:background="#4db6ac" />        
    <TextView            
        android:layout_width="96dp"            
        android:layout_height="match_parent"            
        android:background="#26a69a" />    
</LinearLayout>    
<LinearLayout        
    android:layout_width="match_parent"            
    android:layout_height="match_parent"        
    android:orientation="vertical">        
    <TextView           
        android:layout_width="match_parent"            
        android:layout_height="68dp"            
        android:background="#b2dfdb" />        
    <TextView            
        android:layout_width="match_parent"                
        android:layout_height="68dp"            
        android:background="#80cbc4" />        
    <TextView            
        android:layout_width="match_parent"                
        android:layout_height="68dp"            
        android:background="#4db6ac" />        
    <TextView            
        android:layout_width="match_parent"                    
        android:layout_height="68dp"            
        android:background="#26a69a" />    
</LinearLayout>
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

2.RelativeLayout布局

參考其他控件進行布局,默認為父控件。
有三種類型的屬性:

  • 屬性值是true或false
    • android:layout_centerHrizontal 水平居中
    • android:layout_centerVertical 垂直居中
    • android:layout_centerInparent 相對於父元素完全居中。
    • android:layout_alignParentBottom 位於父元素的下邊緣
    • android:layout_alignParentTop 位於父元素的上邊緣
    • android:layout_alignParentLeft 位於父元素的左邊緣
    • android:layout_alignParentRight 位於父元素的右邊緣
  • 屬性值是”@id/*“
    • android:layout_below 在某元素的下方
    • android:layout_above 在某元素的上方
    • andorid:layout_toRightOf 在某元素的右方
    • android:layout_toLeftOf 在某元素的左方
    • android:layout_alignBottom 和某元素下方對齊
    • android:layout_alignTop 和某元素上方對齊
    • android:layout_alignRight 和某元素右方對齊
    • android:layout_alignLeft 和某元素左方對齊
  • 屬性值是數值
    • android:layout_marginLeft 離某元素左邊緣的距離
    • android:layout_marginRight 離某元素右邊緣的距離
    • android:layout_marginTop 離某元素上邊緣的距離
    • android:layout_marginBottom 離某元素下邊緣的距離

各取一個來寫例子,如圖。

技術分享
註意

  • 如果沒有定義左右,那麽默認在左邊,如果沒有定義上下,默認在上邊。
  • 相同位置,新定義的元素會覆蓋舊的元素。例:1被2覆蓋了。
  • 4只定義了在父元素的下部,左右沒有定義,於是默認就在左邊了。
  • android:layout_below,在某元素的下部並不意味著就一定是緊隨某元素,只是在下部的默認位置。例如:5是在3的下部,但是是在下部的默認左邊。
  • 6為下邊緣對齊3,7為marginLeft=150dp。
  • 8為多個屬性共同定義的結果。首先是在3的右部,然後是垂直居中,然後marginLeft=100dp得到最後位置。

代碼如下:

<?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"
    android:orientation="vertical">

    <TextView
        style="@style/btn_relative"

        android:text="1" />

    <TextView
        style="@style/btn_relative"

        android:text="2" />

    <TextView
        android:id="@+id/txt_center"
        style="@style/btn_relative"

        android:layout_centerInParent="true"

        android:text="3" />

    <TextView
        style="@style/btn_relative"

        android:layout_alignParentBottom="true"

        android:text="4" />

    <TextView
        style="@style/btn_relative"

        android:layout_below="@id/txt_center"
        android:background="#d0d9ff"

        android:text="5" />

    <TextView
        style="@style/btn_relative"

        android:layout_alignBottom="@+id/txt_center"

        android:text="6" />

    <TextView
        style="@style/btn_relative"

        android:layout_marginLeft="150dp"

        android:text="7" />

    <TextView
        style="@style/btn_relative"

        android:layout_centerVertical="true"
        android:layout_marginLeft="100dp"
        android:layout_toRightOf="@id/txt_center"

        android:text="8" />
</RelativeLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

3.MyLayout布局(自定義ViewGroup)

自定義布局主要是重寫兩個方法:

  • onMeasure() 這個是寫自定義容器的大小。
  • onLayout() 這個是寫子元素的布局。
    我自己寫了一個自定義布局,是順序填充會延對角線進行排列。

3.1onMeasure()

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        /**
         * 獲得此ViewGroup上級容器為其推薦的寬和高,以及計算模式
         */
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);

        // 計算出所有的childView的寬和高
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        /**
         * width和height是當wrap_content時使用的屬性。
         */
        int width = 0;
        int height = 0;
        int cCount = getChildCount();
        int cWidth = 0;
        int cHeight = 0;
        /**
         * 在這裏計算當wrap_content時,布局的大小。
         */
        for (int i = 0; i < cCount; i++) {
            View childView = getChildAt(i);
            cWidth = childView.getMeasuredWidth();
            cHeight = childView.getMeasuredHeight();
            width += cWidth;
            height += cHeight;
        }
        /**
         * 如果是wrap_content設置為我們計算的值
         * 否則:直接設置為父容器計算的值
         */
        setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? sizeWidth
                : width, (heightMode == MeasureSpec.EXACTLY) ? sizeHeight
                : height);

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

首先要說一下布局計算模式,即最後的EXACTLY。一共有三種計算模式:

  • MeasureSpec.EXACTLY:精確尺寸,相當於具體數值和match_parent。
  • MeasureSpec.AT_MOST:最大尺寸,相當於 warp_content。
  • MeasureSpec.UNSPECIFIED:未指定尺寸,這種情況不多,一般用於AdapterView。

最後的設定大小時,如果是精確尺寸就是用sizeWidth即獲取的尺寸,如果是最大尺寸就是要我們自己計算的那個尺寸了。
onMeasure()最主要的功能就是計算wrap_content的尺寸設置尺寸
我將這個方法稱為“建畫布”,先建了畫布才能在上面繪圖嘛。

3.2 onLayout()

@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int cCount = getChildCount();

        /**
         * 遍歷所有childView根據其寬和高,以及margin進行布局
         */
        for (int i = 0; i < cCount; i++) {
            View childView = getChildAt(i);
            r = l + childView.getMeasuredWidth();
            b = t + childView.getMeasuredHeight();
            childView.layout(l, t, r, b);
            l += childView.getMeasuredWidth();
            t += childView.getMeasuredHeight();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

這個方法的作用是設置擺放子元素的位置。其中onLayout()傳入的l、t、r、b分別是這樣
技術分享

  • l,t分別對應子元素左上角的left,top坐標
  • r,b分別對應子元素右下角的right,bottom坐標

並且可以使用childview.getMeasuredWidth()和childView.getMeasureHeight()得到子元素的寬和高。
這樣就可以來對每個子元素進行布局了。
我稱這個方法為“定位置”。定完位置後那麽子元素就被放到了我們想要的地方。
這樣一個自定義ViewGroup就可以使用了。
xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<com.example.layoutdemo.MyLayout.MyLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >

        <TextView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#b2dfdb" />

        <TextView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#80cbc4" />

        <TextView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#4db6ac" />

        <TextView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#26a69a" />

</com.example.layoutdemo.MyLayout.MyLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

最後效果如圖:
技術分享

4.FrameLayout布局

幀布局,這個布局的特點是從左上角開始,後面的會覆蓋前面的控件。
代碼如下:

<?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"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="100dp"
        android:textColor="#9c27b0"
        android:text="第一層"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="80dp"
        android:textColor="#e91e63"
        android:text="第二層"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="60dp"
        android:textColor="#e51c23"
        android:text="第三層"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="40dp"
        android:textColor="#5677fc"
        android:text="第四層"/>
</FrameLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

實際效果如下:
技術分享

5.TableLayout布局

表格布局。
它遵循著以下結構:

<TableLayout>
    <TableRow>
    <!-在這裏填充第一行的元素->
    </TableRow>
    <TableRow>
    <!-在這裏填充第二行的元素->
    </TableRow>    
</TableLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

還有幾個重要屬性:

  • 寫在TableLayout中的屬性
    • android:stretchColumns 設置第幾列為伸展(0表示第一列)
    • android:shrinkColumns 設置第幾列為收縮
    • android:collapseColumns 設置第幾列為隱藏
  • 寫在TableRow裏的控件裏的屬性
    • android:layout_column 設置控件在第幾列
    • android:layout_span 設置控件能跨多少列

代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:collapseColumns="2"
    android:shrinkColumns="1"
    android:stretchColumns="0">

    <TableRow
       >
        <TextView android:text="我是伸展的第一列" />

        <TextView android:text="我是收縮的第二列" />

        <TextView android:text="我被隱藏了" />
    </TableRow>

    <TableRow>
        <TextView android:text="我可以伸展的很長很長很長長" />

        <TextView android:text="我可以收縮,我可以變的很深很深很深" />

        <TextView android:text="我被隱藏了T_T" />
    </TableRow>

    <TableRow>
        <TextView
            android:layout_column="1"
            android:text="我要在第2列" />
    </TableRow>

    <TableRow>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_column="0"
            android:layout_span="2"
            android:text="我要               跨                  兩                列" />
    </TableRow>
</TableLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

最後效果如下:
技術分享

6.AbsoluteLayout布局

絕對布局,極力不推薦,官方已經舍棄。
定義兩個控件左上角坐標軸
android:layout_xandroid:layout_y來控制位置。

<?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
        style="@style/btn_relative"

        android:text="1" />

    <TextView
        style="@style/btn_relative"
        android:layout_x="60dp"
        android:layout_y="60dp"
        android:text="1" />

    <TextView
        style="@style/btn_relative"
        android:layout_x="160dp"
        android:layout_y="160dp"
        android:text="1" />

    <TextView
        style="@style/btn_relative"
        android:layout_x="260dp"
        android:layout_y="260dp"
        android:text="1" />
</AbsoluteLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

最後效果如下:
技術分享

原文連接:http://blog.csdn.net/u013254061/article/details/52512146

【Android】Android六種布局詳解