這篇就對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>
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>
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); }
首先要說一下布局計算模式,即最后的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(); } }
這個方法的作用是設置擺放子元素的位置。其中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>
最后效果如圖:
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>
實際效果如下:
5.TableLayout布局
表格布局。
它遵循着以下結構:
<TableLayout> <TableRow> <!-在這里填充第一行的元素-> </TableRow> <TableRow> <!-在這里填充第二行的元素-> </TableRow> </TableLayout>
還有幾個重要屬性:
- 寫在TableLayout中的屬性
- android:stretchColumns 設置第幾列為伸展(0表示第一列)
- android:shrinkColumns 設置第幾列為收縮
- android:collapseColumns 設置第幾列為隱藏
- 寫在TableRow里的控件里的屬性
- android:layout_column 設置控件在第幾列
- android:layout_span 設置控件能跨多少列
- android:gravity 設置控件的排列方式,可以水平居中,水平靠左,水平靠右,垂直居中,垂直靠右,垂直靠左
代碼如下:
<?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>
最后效果如下:
如果想要設置兩個一個並排顯示的,可以參考下面的代碼:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/daylimit_content_alter" android:layout_width="match_parent" android:layout_height="match_parent" > <TableLayout android:layout_width="fill_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:collapseColumns="2" > <TableRow android:gravity="center_horizontal" > <Button android:layout_weight="0.5" android:onClick="CopyBtn" android:text="復制" /> <Button android:layout_weight="0.5" android:onClick="" android:text="返回" /> </TableRow> </TableLayout> </RelativeLayout>
效果圖:
6.AbsoluteLayout布局
絕對布局,極力不推薦,官方已經舍棄。
定義兩個控件左上角坐標軸
即android:layout_x 和android: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>
最后效果如下:
原文連接:http://blog.csdn.net/u013254061/article/details/52512146