Android SDK 定義了多種布局方式以方便用戶設計 UI。各種布局方式均為 ViewGroup 類的子類,結構如圖 1 所示。
Android五大布局:FrameLayout(單幀布局)、LinearLayout(線性布局)、AbsoluteLayout(絕對布局)、RelativeLayout(相對布局)和TableLayout(表格布局)
- 這是Android在最初發布時的五大布局,但在2.0時,將AbsoluteLayout(絕對布局)被標志已過期,可以用幀布局和相對布局進行管理布局。
- 在Android 4.0 時,引入GridLayout(網格布局),和 TableLayout(表格布局) 有點類似,不過它功能更多,也更加好用。
而ConstraintLayout
,可以翻譯為約束布局,在2016年Google I/O 大會上發布。可以在Api9以上的Android系統使用它,它的出現主要是為了解決布局嵌套過多的問題,以靈活的方式定位和調整小部件。- 所以有人會說,Android有四種、五種、六種、甚至七種,都是對的!!
以下將對常用的五大布局介紹:FrameLayout(單幀布局)、LinearLayout(線性布局)、ConstraintLayout (約束布局)、TableLayout(表格布局)和RelativeLayout(相對布局)。
LinearLayout(線性布局)
- 線性布局(LinearLayout)主要以水平或垂直方式來顯示界面中的控件。
- 當控件水平排列時,顯示順序依次為從左到右;
- 當控件垂直排列時,顯示順序依次為從上到下。
- 線性布局中,每行或每列中只允許有一個子視圖或控件。
-
LinearLayout的最主要的屬性有:
-
android:gravity:設置內部控件的顯示位置。
-
android:orientation:設置內部控件的排列方向,常量horizontal(默認值)表示水平排列,vertical表示垂直排列。
-
android:layout_weight:設置內部控件在LinearLayout中所占的權重。
-
-
注意:當控件使用權重屬性時,布局寬度或高度屬性值通常設置為0。
-
所有的組件都有一個 layout_weight 值,默認為0。意思是需要顯示多大的視圖就占據多大的屏幕空間。
-
若賦值為大於 0 的值,則將可用的空間分割,分割的大小取決於當前的 layout_weight 數值與其他空間的 layout_weight 值的比率,即權重。
-
實例 LinearLayoutDemo 演示了 LinearLayout 布局的使用方法,效果如下圖所示。
- 點擊Layout,右鍵New->Layout resource file,給這個布局起一個名字。
- 新建了一個two.xml->點擊Design->拖拽Button(3個)->形成如下圖:
- 按住Ctrl,點擊圖中三個Button,再點擊右側菜單中layout_width的下拉菜單,將match_parent改為wrap_content,形成如圖:
- 點擊Text,查看相關代碼,如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="vertical" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent"> 6 7 <Button 8 android:id="@+id/button7" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:text="Button" /> 12 13 <Button 14 android:id="@+id/button8" 15 android:layout_width="wrap_content" 16 android:layout_height="wrap_content" 17 android:text="Button" /> 18 19 <Button 20 android:id="@+id/button10" 21 android:layout_width="wrap_content" 22 android:layout_height="wrap_content" 23 android:text="Button" /> 24 </LinearLayout>
- 將第三行的vertical,改為horizontal,可以看到一改完這個界面就變成水平排列的了。
- LinearLayout 布局通過 android:orientation="horizontal" 屬性將布局設置為橫向線性排列。
- LinearLayout 布局通過 android:orientation="vertical" 屬性將布局設置為縱向線性排列。
- 在上面的代碼第三與第四行之間添加一句:android:gravity="center",可以看到三個button就居中了(左圖),而改為android:gravity="center_horizontal",可以看到三個button就水平居中了(右圖)。
將源代碼改為如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="vertical" 4 android:gravity="center" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent"> 7 8 <Button 9 android:id="@+id/button7" 10 android:layout_weight="1" 11 android:layout_width="wrap_content" 12 android:layout_height="0dp" 13 android:text="Button" /> 14 15 <Button 16 android:id="@+id/button8" 17 android:layout_weight="1" 18 android:layout_width="wrap_content" 19 android:layout_height="0dp" 20 android:text="Button" /> 21 22 <Button 23 android:id="@+id/button10" 24 android:layout_weight="1" 25 android:layout_width="wrap_content" 26 android:layout_height="0dp" 27 android:text="Button" /> 28 </LinearLayout>
- 你可能會奇怪,每一個button中有兩個android:layout_weight,
- 第一個則是每個button在其中所占的權重,而上面有三個,每個都為1,則每個的權重即:每個權重(即1)/所有權重的和(即3),也就是1/3;如上圖所示!!!
- 第二個wrap_content:是layout_width和layout_height的屬性值之一,表示和自身內容一樣的長度。
- LinearLayout 布局可使用嵌套。活用 LinearLayou 布局可以設計出各種各樣漂亮的布局方式。
約束布局ConstraintLayout
- 約束布局ConstraintLayout是一個ViewGroup,可以在Api9以上的Android系統使用它,它的出現主要是為了解決布局嵌套過多的問題,以靈活的方式定位和調整小部件。
- ConstraintLayout是Google在2016年的Google I/O大會上提出的一個可以靈活控制子控件的位置和大小的新布局。官方文檔
- 從 Android Studio 2.3起,官方的模板默認使用 ConstraintLayout。所以可見ConstraintLayout的重要性。
-
ConstraintLayout可以在不嵌套ViewGroup的情況下實現非常龐大、復雜的布局,實現扁平化。
-
ConstraintLayout同時具有RelativeLayout和LinearLayout的優點、特
性、功能強大。
-
-
ConstraintLayout無論是通過布局管理器拖搜,鼠標控制的形式實現還
是使用XML代碼去寫,都比較方便。
- 對於新手,建議先學會線性布局和相對布局,再學習約束布局,效果可能會更好!!!
默認情況下,Android Studio建立的工程,它的主界面就是約束布局的。
實例 MyApplication 演示了 ConstraintLayout 布局的使用方法,效果如圖所示。
實例 MyApplication 中 activity_main.xml的代碼如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <androidx.constraintlayout.widget.ConstraintLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 xmlns:app="http://schemas.android.com/apk/res-auto" 5 xmlns:tools="http://schemas.android.com/tools" 6 android:layout_width="match_parent" 7 android:layout_height="match_parent" 8 tools:context=".MainActivity"> 9 10 <TextView 11 android:id="@+id/textView" 12 android:layout_width="wrap_content" 13 android:layout_height="wrap_content" 14 android:text="Hello World!" 15 app:layout_constraintBottom_toBottomOf="parent" 16 app:layout_constraintLeft_toLeftOf="parent" 17 app:layout_constraintRight_toRightOf="parent" 18 app:layout_constraintTop_toTopOf="parent" /> 19 20 <Button 21 android:id="@+id/button4" 22 android:layout_width="wrap_content" 23 android:layout_height="wrap_content" 24 android:layout_marginStart="32dp" 25 android:layout_marginTop="60dp" 26 android:layout_marginEnd="280dp" 27 android:text="Button" 28 app:layout_constraintEnd_toEndOf="parent" 29 app:layout_constraintStart_toStartOf="parent" 30 app:layout_constraintTop_toTopOf="parent" /> 31 32 <Button 33 android:id="@+id/button5" 34 android:layout_width="wrap_content" 35 android:layout_height="wrap_content" 36 android:layout_marginStart="53dp" 37 android:layout_marginTop="39dp" 38 android:text="Button" 39 app:layout_constraintStart_toEndOf="@+id/button4" 40 app:layout_constraintTop_toBottomOf="@+id/button4" /> 41 42 <androidx.constraintlayout.widget.Guideline 43 android:id="@+id/guideline" 44 android:layout_width="wrap_content" 45 android:layout_height="wrap_content" 46 android:orientation="vertical" 47 app:layout_constraintGuide_begin="267dp" /> 48 49 <androidx.constraintlayout.widget.Guideline 50 android:id="@+id/guideline2" 51 android:layout_width="wrap_content" 52 android:layout_height="wrap_content" 53 android:orientation="horizontal" 54 app:layout_constraintGuide_begin="247dp" /> 55 56 </androidx.constraintlayout.widget.ConstraintLayout>
該布局中放置了兩個 ConstraintLayout 布局對象。
- 其中Button4有三個約束條件,分別是對應距離左邊距32dp,距離右邊距280dp,距離上邊距60dp
-
而Button5則只有兩個邊距,分別是它的左邊距距離Button4的右邊距為53dp,它的上邊距距離 Button4的下邊距為39dp
- 相關屬性如下:參考
四周牽引 |
layout_constraintLeft_toLeftOf: 將目標控件的左側牽引到另外一個控件的左側 |
layout_constraintRight_toLeftOf: 將目標控件的右側牽引到另外一個控件的左側 |
layout_constraintLeft_toRightOf: 將目標控件的左側牽引到另外一個控件的右側 |
layout_constraintRight_toRightOf: 將目標控件的右側牽引到另外一個控件的右側 |
layout_constraintTop_toTopOf: 將目標控件的上側牽引到另外一個控件的上側 |
layout_constraintTop_toBottomOf: 將目標控件的上側牽引到另外一個控件的下側 |
layout_constraintBottom_toTopOf: 將目標控件的下側牽引到另外一個控件的上側 |
layout_constraintBottom_toBottomOf: 將目標控件的下側牽引到另外一個控件的下側 |
基線對齊 |
layout_constrainBaseline_toBaselineOf:與目標控件的基線對齊 |
start,end類(與left,right類似) |
layout_constrainStart_toEndOf:將目標控件的左側與另一控件的右側對齊 |
layout_constrainStart_toStartOf:將目標控件的左側與另一控件的左側對齊 |
layout_constrainEnd_toStartOf:將目標控件的右側與另一控件的左側對齊 |
layout_constrainEnd_toEndOf:將目標控件的右側與另一控件的右側對齊 |
布局邊距 |
layout_marginStart:左邊距 |
layout_marginEnd:右邊距 |
layout_marginLeft:左邊距 |
layout_marginRight:右邊距 |
layout_marginLeft:左邊距 |
layout_marginTop:上邊距 |
layout_marginBottom:下邊距 |
基准線(guideline) |
orientation:vertical/horizontal 基准線的方向 |
layout_constrainGuide_begin:基准線起點 |
layout_constrainGuide_end:基准線終點 |
layout_constrainGuide_percent:基准線百分比模式,用於指定位置 |
牽引力 |
layout_constrainHorizontal_bias:水平方向上的牽引力 |
layout_constrainVertical_bias:垂直方向上的牽引力 |
FrameLayout(單幀布局)
- FrameLayout 又稱單幀布局,是 Android 所提供的布局方式里最簡單的布局方式,它指定屏幕上的一塊空白區域,在該區域填充一個單一對象。例如圖片、文字、按鈕等。
-
幀布局主要掌握以下兩個屬性的使用:android:layout_gravity、android:visibility
-
默認情況下,控件位於幀布局的左上角。可通過控件的 android:layout_gravity屬性控制其位置。
-
android:layoutgravity屬性可設置為下列值:
-
top:控件位於布局頂部。
-
bottom:控件位於布局底部,單獨使用時等價於“left|bottom“。
-
left:控件位於布局左側。
-
right:控件位於布局右側,單獨使用時等價於“top|right“。
-
center:控件位於布局中心。
-
center_vertical:控件位於垂直方向上的中間位置,單獨使用時等價於“left|centervertical“。
-
center_horizontal:控件位於水平方向上的中間位置,單獨使用時等價於“top|center_horizontal“。
-
-
gravity的中文意思就是“重心“,就是表示view橫向和縱向的停靠位置。
-
android:gravity:是對控件本身來說的,是用來設置控件本身的內容應該顯示在控件的什么位置,默認值是左側,也可以用來設置布局中的控件位置。
- android:layout_gravity:是相對於包含該控件的父控件來說的,設置該控件在父控件的什么位置。
- android:visibility
- View.VISIALBE 可見,顯示到頁面
- View.INVISIABLE不可見,但是還是占用位置
- View.GONE隱藏,不可見並且不占用位置
實例演示了 FrameLayout 的布局效果。該布局中有 3個組件,前2個組件為ImageView 以默認方式放置到布局中,其中一個不顯示,另一個顯示,第 3 個組件為 Button讓它居中,運行效果如圖。
1 <?xml version="1.0" encoding="utf-8"?> 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 android:layout_width="match_parent" android:layout_height="match_parent"> 5 6 7 <ImageView 8 android:id="@+id/imageView" 9 android:visibility="invisible" 10 android:layout_width="wrap_content" 11 android:layout_height="wrap_content" 12 app:srcCompat="@android:drawable/btn_dialog" /> 13 14 <ImageView 15 android:id="@+id/imageView2" 16 android:visibility="visible" 17 android:layout_width="wrap_content" 18 android:layout_height="wrap_content" 19 app:srcCompat="@android:drawable/arrow_down_float" /> 20 21 <Button 22 android:id="@+id/button" 23 android:layout_gravity="center" 24 android:layout_width="wrap_content" 25 android:layout_height="wrap_content" 26 android:text="Button" /> 27 </FrameLayout>
1 package com.example.myapplication; 2 3 import androidx.appcompat.app.AppCompatActivity; 4 5 import android.os.Bundle; 6 import android.view.View; 7 import android.widget.Button; 8 import android.widget.ImageView; 9 10 public class MainActivity extends AppCompatActivity { 11 private Button button; 12 private ImageView imageView1,imageView2; 13 private int count; 14 15 @Override 16 protected void onCreate(Bundle savedInstanceState) { 17 super.onCreate(savedInstanceState); 18 setContentView(R.layout.syhdt); 19 20 button = (Button)findViewById(R.id.button); 21 imageView1 = (ImageView)findViewById(R.id.imageView); 22 imageView2 = (ImageView)findViewById(R.id.imageView2); 23 24 button.setOnClickListener(new View.OnClickListener(){ 25 @Override 26 public void onClick(View v) { 27 if(count%2==0){ 28 imageView1.setVisibility(View.VISIBLE); 29 imageView2.setVisibility(View.INVISIBLE); 30 }else{ 31 imageView1.setVisibility(View.INVISIBLE); 32 imageView2.setVisibility(View.VISIBLE); 33 } 34 count++; 35 } 36 }); 37 } 38 }
其中:
1 android:layout_width="wrap_content" 2 android:layout_height="wrap_content"
表明 FrameLayout 布局覆蓋了整個屏幕空間。
表格布局(TableLayout)
- 表格布局(TableLayout)是以表格形式排列控件的,通過行和列將界面划分為多個單元格,每個單元格都可以添加控件。
- 表格布局需要和TableRow配合使用,每一行都由TableRow對象組成,因此TableRow的數量決定表格的行數。而表格的列數是由包含最多控件的TableRow決定的,例如第1個TableRow有兩個控件,第2個TableRow有三個控件,則表格列數為3。
表格布局屬性
- android:stretchColumns設置該列被拉伸
- android:shrinkColumns設置該列被收縮
- android:collapseColumns設置該列被隱藏
表格布局控件屬性
- android:layout_column設置該單元顯示位置
- android:layout_span設置該單元格占據幾列,默認為1列
實例演示了使用 TableLayout 制作 UI 的方法,效果如圖所示。
- 不廢話上代碼:
1 <?xml version="1.0" encoding="utf-8"?> 2 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:stretchColumns="2" 5 android:layout_height="match_parent"> 6 7 <TableRow 8 android:gravity="center" 9 android:layout_width="match_parent" 10 android:layout_height="match_parent" > 11 12 <Button 13 android:id="@+id/button2" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 android:text="Button" /> 17 18 <Button 19 android:id="@+id/button3" 20 android:layout_width="wrap_content" 21 android:layout_height="wrap_content" 22 android:text="Button" /> 23 24 <Button 25 android:id="@+id/button4" 26 android:layout_width="wrap_content" 27 android:layout_height="wrap_content" 28 android:text="Button" /> 29 </TableRow> 30 31 <TableRow 32 android:layout_width="match_parent" 33 android:layout_height="match_parent" > 34 35 <Button 36 android:id="@+id/button5" 37 android:layout_width="wrap_content" 38 android:layout_height="wrap_content" 39 android:text="Button" /> 40 41 <Button 42 android:id="@+id/button6" 43 android:layout_column="2" 44 android:layout_width="wrap_content" 45 android:layout_height="wrap_content" 46 android:text="Button" /> 47 </TableRow> 48 </TableLayout>
- 創建了兩個 TableRow ,第一個 TableRow有三個Button,並讓它們居中;第二個 TableRow 有兩個Button, 讓其中的第二個在第三列,並讓整體第三列拉伸。具體如上圖顯示。
RelativeLayout(相對布局)
- 從名稱上可以看出,這種布局方式是以一種讓組件以相對於容器或者相對於容器中的另一個組件的相對位置進行放置的布局方式。
- RelativeLayout 布局提供了一些常用的布局設置屬性用於確定組件在視圖中的相對位置。下面列舉了 RelativeLayout 相關屬性及其所代表的含義。
相對於父元素控件布局
屬性 | 含義 |
---|---|
android:layout_centerHrizontal | 水平居中 |
android:layout_centerVertical | 垂直居中 |
android:layout_centerInparent | 相對於父元素完全居中 |
android:layout_alignParentBottom | 位於父元素的下邊緣 |
android:layout_alignParentLeft | 位於父元素的左邊緣 |
android:layout_alignParentRight | 位於父元素的右邊緣 |
android:layout_alignParentTop | 位於父元素的上邊緣 |
android:layout_alignWithParentIfMissing | 如果對應的兄弟元素找不到的話就以父元素做參照物 |
相對於某個元素控件布局
注意:屬性值必須為id的引用名“@id/id-name”
屬性 | 含義 |
---|---|
android:layout_below | 位於元素的下方 |
android:layout_above | 位於元素的的上方 |
android:layout_toLeftOf | 位於元素的左邊 |
android:layout_toRightOf | 位於元素的右邊 |
android:layout_alignTop | 該元素的上邊緣和某元素的的上邊緣對齊 |
android:layout_alignLeft | 該元素的左邊緣和某元素的的左邊緣對齊 |
android:layout_alignBottom | 該元素的下邊緣和某元素的的下邊緣對齊 |
android:layout_alignRight | 該元素的右邊緣和某元素的的右邊緣對齊 |
相對像素值
屬性 | 含義 |
---|---|
android:layout_marginBottom | 底邊緣的距離 |
android:layout_marginLeft | 左邊緣的距離 |
android:layout_marginRight | 右邊緣的距離 |
android:layout_marginTop | 上邊緣的距離 |
實例演示了相對布局的使用方法,其運行效果如圖所示。
- 上代碼
1 <?xml version="1.0" encoding="utf-8"?> 2 3 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="fill_parent" 5 android:layout_height="fill_parent"> 6 7 <TextView 8 android:id="@+id/label" 9 android:layout_width="fill_parent" 10 android:layout_height="wrap_content" 11 android:text="hello" /> 12 13 <EditText 14 android:id="@+id/enter" 15 android:layout_width="fill_parent" 16 android:layout_height="wrap_content" 17 android:layout_alignParentLeft="true" 18 android:layout_below="@+id/label" /> 19 20 <Button 21 android:id="@+id/button1" 22 android:layout_width="wrap_content" 23 android:layout_height="wrap_content" 24 android:layout_alignParentRight="true" 25 android:layout_below="@+id/enter" 26 android:text="butltext" /> 27 28 <Button 29 android:id="@+id/ok" 30 android:layout_width="wrap_content" 31 android:layout_height="wrap_content" 32 android:layout_alignBottom="@+id/button1" 33 android:layout_alignParentLeft="true" 34 android:text="but2text" /> 35 36 </RelativeLayout>
該 RelativeLayout 布局的過程如下:
- 放置一個 ID 為 label 的 TextView 組件。
- 通過 android:layout_below="@+id/label" 屬性將 ID 為 enter 的組件 EditText 放置到 TextView 的下面。
- 在布局中加入一個 ID 為 button1 的 Button,通過 android:layout_below="@+id/enter" 屬性將該 Button 放置到 enter 的下面,通過 android:layout_alignParentRight= "true" 屬性將 Button 放置到相對布局的右側。
- 在相對布局中加入一個名為 ok 的 Button,通過 android:layout_alignBottom="@+ id/button1" 屬性將該 Button 底邊與 button1 對齊,通過 android:layout_alignParentLeft ="true" 屬性將該 Button 放置到布局的左邊。