Android總體有五大布局:
- 線性布局(LiearLayout): 螢幕垂直或水平方向布局。
- 幀布局(FrameLayout):控制項從螢幕左上方開始布局。
- 相對布局(RelativeLayout): 以其他控制項為參照布局。
- 絕對布局(AbsoluteLayout):以螢幕座標布局。
- 表格版面配置(TableLayout):按照行列方式布局。
一、LinearLayout
線性布局在開發中使用最多,具有垂直方向與水平方向的布局方式,通過設定屬性“android:orientation”控制方向,屬性值垂直(vertical)和水平(horizontal),預設水平方向。
在使用orientation時需要注意一個問題,假如我們使用預設布局方向,即水平方向,若LinearLayout中存在不止一個控制項且都未設定具體寬度,即這樣的布局代碼:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content"/></LinearLayout>
則會出現下面的錯誤:
這個錯誤告訴我們在有多個子控制項時需要設定布局方向或至少設定一個子控制項在該布局方向的大小,我們可以顯示設定布局方向或設定某一個子控制項的寬度。
除orientation之外還有以下常用屬性:
android:gravity:內部控制項對齊,常用屬性值有center、center_vertical、center_horizontal、top、bottom、left、right等。這個屬性在布局組件RelativeLayout、TableLayout中也有使用,FrameLayout、AbsoluteLayout則沒有這個屬性。
center:置中顯示,這裡並不是表示顯示在LinearLayout的中心,當LinearLayout線性方向為垂直方向時,center表示水平置中,但是並不能垂直置中,此時等同於center_horizontal的作用;同樣當線性方向為水平方向時,center表示垂直置中,等同於center_vertical。
top、bottom、left、right顧名思義為內部控制項居頂、低、左、右布局。
這裡要與android:layout_gravity區分開,layout_gravity是用來設定自身相對於父元素的布局。
android:layout_weight:權重,用來分配當前控制項在剩餘空間的大小。正常情況下,值越大佔據高度或寬度越大。例外的情況,在LineayLayout布局中使用這個屬性時需要注意: 當水平方向布局且子控制項的寬度為fill_parent或match_parent時,值越小佔據寬度越大,垂直方向也一樣。分析一下這種情況,類似這樣的代碼:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="40dp" android:background="#666666" android:text="第一個子控制項" android:gravity="center" android:layout_weight="1"/> <TextView android:layout_width="match_parent" android:layout_height="40dp" android:background="#EE4000" android:text="第二個子控制項" android:gravity="center" android:layout_weight="2"/></LinearLayout>
顯示效果:
這裡出現這種情況主要是因為match_parent或fill_parent引起的,系統先給第一個子控制項分配parent_width(剩餘空間),再給第二個分配parent_width,即分配了兩個parent_width,此時剩餘為parent_width-2parent_width=-parent_width,這裡主要問題就在這裡,剩餘控制項其實已經為一個負數了。接著,第一個控制項占寬度:parent_width(當前已有寬度)+權重1/3*(-parent_width)=2/3parent_width;第二個控制項占寬度:parent_width+權重2/3*(-parent_width)=1/3parent_width,所以當寬度都是match_parent時,剩餘空間則為負數,誰的權重大誰就會減去越多。
在平常開發中我們會經常用到這個屬性,通過設定layout_weight能解決很多不可思議的布局問題。
二、FrameLayout
幀布局或叫層布局,從螢幕左上方按照層次堆疊布局,後面的控制項覆蓋前面的控制項。該布局在開發中經常用到,因為是按層次方式布局,我們需要實現層面顯示的樣式時就可以採用這種布局方式,比如我們要實現一個類似百度地圖的布局:
通過這張圖我們可以看到地圖與操作按鈕是分層顯示的,運用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"> <com.baidu.mapapi.map.MapView android:id="@+id/mapShowView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true"/> <EditText android:layout_width="match_parent" android:layout_height="40sp" android:background="@drawable/edit_selector" android:layout_marginLeft="20sp" android:layout_marginRight="20sp" android:layout_marginTop="30dp" android:paddingLeft="10sp" android:textSize="14sp" android:hint="搜地點、查公交、找路線" android:textColorHint="#aaaaaa" android:gravity="left|center_vertical"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="right" android:layout_marginTop="80dp" android:layout_marginRight="20dp"> <Button android:id="@+id/traffic" android:layout_width="45sp" android:layout_height="45sp" android:text="路況" android:textColor="#ffffff" android:textSize="14sp" android:background="@drawable/corner_black_bgborder"/> <Button android:id="@+id/panorama" android:layout_width="45sp" android:layout_height="45sp" android:text="全景" android:textColor="#ffffff" android:textSize="14sp" android:layout_marginTop="10dp" android:background="@drawable/corner_black_bgborder"/> <Button android:id="@+id/company" android:layout_width="45sp" android:layout_height="45sp" android:text="同行" android:textColor="#ffffff" android:textSize="14sp" android:layout_marginTop="10dp" android:background="@drawable/corner_black_bgborder"/> </LinearLayout> <Button android:id="@+id/location" android:layout_width="45sp" android:layout_height="45sp" android:layout_gravity="bottom" android:text="定位" android:textColor="#ffffff" android:textSize="14sp" android:layout_marginLeft="20dp" android:layout_marginBottom="120dp" android:background="@drawable/corner_black_bgborder"/></FrameLayout>
顯示效果:
FrameLayout中第一個子控制項為百度地圖,其次為輸入框、右邊操作按鈕與左下方定位按鈕。我們可以看到這裡很多子控制項都使用了一個屬性,layout_gravity,正如前面講解gravity屬性提到的一樣,layout_gravity用來設定自身相對於父元素的布局,這個屬性在FrameLayout布局時會經常使用到,用來控制控制項在布局中的位置,layout_gravity常用屬性值有top、bottom、left、right、center、center_horizontal、center_vertical,這裡的center可以讓控制項居於FrameLayout的中心布局,屬性值可以複合使用,比如我們既要居底部布局又要垂直置中就可以這樣設定:“android:layout_gravity=bottom|center_vertical”。
代碼中的操作控制項分三個布局位置,頂部的搜尋方塊、右邊的操作按鈕、左下方的定位按鈕。以下為這三部分的講解:
1、搜尋輸入框,根據FrameLayout的定義,子控制項從布局的左上方開始按照層次堆疊布局,這裡輸入框,我們需要顯示在螢幕的上方,所以只需要設定它的上、左、右方向的margin就可以滿足我們的設計。這裡讓輸入框水平置中顯示的方式是通過設定寬度為match_parent再設定左右方向相同的margin就可以水平置中,當然也可以通過設定一定的寬度後再設定layout_gravity的屬性值為center_horizontal。
2、右邊操作按鈕欄,三個按鈕為LinearLayout布局,垂直方向線性布局,LinearLayout中我們設定“android :layout_gravity=right”來讓實現靠右布局,其次設定margin讓控制項按照合理的布局顯示。
3、定位按鈕,這個按鈕顯示在螢幕的左下方,我們只需要設定“android :layout_gravity=bottom”,再設定方向的margin讓按鈕顯示在合理的位置。
三、RelativeLayout
相對布局可以讓子控制項相對於兄弟控制項或父控制項進行布局,可以設定子控制項相對於兄弟控制項或父控制項進行上下左靠右對齊。RelativeLayout能替換一些嵌套視圖,當我們用LinearLayout來實現一個簡單的布局但又使用了過多的嵌套時,就可以考慮使用RelativeLayout重新布局。
RelativeLayout中子控制項常用屬性:
1、相對於父控制項,例如:android:layout_alignParentTop=“true”
android:layout_alignParentTop 控制項的頂部與父控制項的頂部對齊;
android:layout_alignParentBottom 控制項的底部與父控制項的底部對齊;
android:layout_alignParentLeft 控制項的左部與父控制項的左部對齊;
android:layout_alignParentRight 控制項的右部與父控制項的右部對齊;
2、相對給定Id控制項,例如:android:layout_above=“@id/**”
android:layout_above 控制項的底部置於給定ID的控制項之上;
android:layout_below 控制項的底部置於給定ID的控制項之下;
android:layout_toLeftOf 控制項的右邊緣與給定ID的控制項左邊緣對齊;
android:layout_toRightOf 控制項的左邊緣與給定ID的控制項右邊緣對齊;
android:layout_alignBaseline 控制項的baseline與給定ID的baseline對齊;
android:layout_alignTop 控制項的頂部邊緣與給定ID的頂部邊緣對齊;
android:layout_alignBottom 控制項的底部邊緣與給定ID的底部邊緣對齊;
android:layout_alignLeft 控制項的左邊緣與給定ID的左邊緣對齊;
android:layout_alignRight 控制項的右邊緣與給定ID的右邊緣對齊;
3、置中,例如:android:layout_centerInParent=“true”
android:layout_centerHorizontal 水平置中;
android:layout_centerVertical 垂直置中;
android:layout_centerInParent 父控制項的中央;
應用執行個體:
<?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"> <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="@drawable/topbar_bg_border"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="標題" android:textSize="19sp" android:textStyle="bold" android:textColor="#4e6288"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:layout_marginRight="15dp" android:text="取消" android:textSize="18sp"/> </RelativeLayout></LinearLayout>
顯示結果:
這是一個頂部配置樣式,在很多app中我們會考慮使用樣式基本相同的頂部布局來統一風格。這隻是一個簡單的布局,包含一個Title以及取消按鈕(這裡用的TextView代替),相對於其他幾個布局控制項,RelativeLayout在這裡使用起來更簡單也更合理。首先設定RelativeLayout的高度,再設定Title的android:layout_centerInParent=”true”顯示在中央,最後設定取消按鈕的兩個屬性垂直置中android:layout_centerVertical=”true”和右部對齊android:layout_alignParentRight=”true”。
四、AbsoluteLayout
絕對布局也叫座標布局,指定控制項的絕對位置,簡單直接,直觀性強,但是手機螢幕尺寸差別較大,適應性差,Android 1.5已棄用,可以用RelativeLayout替代。
AbsoluteLayout實現布局代碼:
<?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"> <ImageView android:layout_width="100dip" android:layout_height="120dip" android:layout_x="150dip" android:layout_y="40dip" android:src="@drawable/android_logo"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="100dip" android:layout_y="150dip" android:text="上一張"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="200dip" android:layout_y="150dip" android:text="下一張"/> </AbsoluteLayout>
顯示效果:
這裡為了設計一個圖片瀏覽的效果,將各個控制項的layout_x與layout_y依次設定了一遍,然而當前螢幕尺寸能正常顯示,其他螢幕就需要重新制定布局。其實用RelativeLayout輕鬆就能實現這樣的效果,還不用考慮螢幕相容性。 所以,AbsoluteLayout已成為android布局中的曆史。
五、TableLayout
表格版面配置繼承自LinearLayout,通過TableRow設定行,列數由TableRow中的子控制項決定,直接在TableLayout中添加子控制項會佔據整個一行。
TableLayout常用屬性:
android:shrinkColumns:設定可收縮的列,內容過多就收縮顯示到第二行
android:stretchColumns:設定可伸展的列,將空白地區填充滿整個列
android:collapseColumns:設定要隱藏的列
列的索引從0開始,shrinkColumns和stretchColumns可以同時設定。
子控制項常用屬性:
android:layout_column:第幾列
android:layout_span:佔據列數
TableLayout執行個體代碼:
<?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"> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="首頁"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center"> <TableLayout android:layout_width="match_parent" android:layout_height="match_parent" android:stretchColumns="0,1,2" android:gravity="center"> <TableRow> <TextView android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="5dp" android:background="#e2a617" android:text="檔案管理" android:gravity="center"/> <TextView android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="5dp" android:background="#0d637f" android:text="市集" android:gravity="center"/> <TextView android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="5dp" android:background="#aa2266" android:text="檔案管理" android:gravity="center"/> </TableRow> <TableRow> <TextView android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="5dp" android:background="#45e15f" android:text="應用管理" android:gravity="center"/> <TextView android:layout_width="200dp" android:layout_height="100dp" android:layout_margin="5dp" android:background="#3924a4" android:text="應用中心" android:gravity="center" android:layout_span="2"/> </TableRow> </TableLayout> </LinearLayout> <TableLayout android:layout_width="match_parent" android:layout_height="55dp" android:background="#f5f5f5" android:stretchColumns="0,1,2,3" android:gravity="center_vertical"> <TableRow> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="首頁" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="訊息" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="發現" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="我" /> </TableRow> </TableLayout></LinearLayout>
顯示效果:
螢幕中心是一個類似Material布局,底部是一個頁面切換的導覽列。底部布局通過設定android:stretchColumns=”0,1,2,3″來讓四個按鈕同樣大小顯示並填充到整個寬度,中心地區主要使用android:stretchColumns=”0,1,2″填充顯示以及android:layout_span=”2″控制大內容跨列顯示。
布局在Android介面中相當於建築物的架構,在開發中我們需要運用多種布局來實現介面顯示需求,只有瞭解了各種布局的顯示樣式與它們之間的差距,我們才能駕輕就熟、合理的布局介面。