主頁 > 移動端開發 > Android從零開始-LayoutManager詳解

Android從零開始-LayoutManager詳解

2021-06-10 07:55:34 移動端開發

布局概述

為了讓組件(TextView,Button等)在不同的手機螢屏上都能運行良好(不同手機螢屏解析度、尺寸并不完全相同),如果讓程式手動控制每個組件的大小、位置,則將給編程帶來巨大的困難,為了解決這個問題,Android提供了布局管理器,布局管理器可以根據運行平臺來調整組件的大小,咱們程式員要做的只是為容器選擇合適的布局管理器,

每當Acitivity.setContentView(@LayoutRes int layoutResID)方法被呼叫,或者一個View通過LayoutInflater物件inflater出來,那么相關的布局檔案就會被加載并決議出來,XML檔案中每個大寫的XML節點對應著一個View物件,他們被系統實體化,在Acitviity或者Fragment的整個生命周期中,他們都是UI層級的一部分,這會影響到應用程式使用程序中的分配,

Android的布局管理器本身就是個UI組件,所有的布局管理器都是ViewGroup的子類,而ViewGroup是View的子類,所以布局管理器可以當成普通的UI組件使用,也可以作為容器類使用,可以呼叫多個多載addView()向布局管理器中添加組件,并且布局管理器可以互相嵌套,當然不推薦過多的嵌套(如果要兼容低端機型,最好不要超過5層),

布局層級管理

讓咱們一起了解一下每當系統繪制一個布局時,都會發生一些什么,這一程序由兩個步驟完成:

1、繪制(Measurement)

a、根布局測量自身,

b、根布局要求它內部所有子組件測量自身,

c、所有自布局都需要讓它們內部的子組件完成這樣的操作,直到遍歷完視圖層級中所有的View,

2、擺放( Positioning)

a、當布局中所有的View都完成了測量,根布局則開始將它們擺放到合適的位置,

b、所有子布局都需要做相同的事情,直到遍歷完視圖層級中所有的View,

當某個View的屬性發生變化(如:TextView內容變化或ImageView影像發生變化),View自身會呼叫View.invalidate()方法(必須從 UI 執行緒呼叫),自底向上傳播該請求,直到根布局(根布局會計算出需要重繪的區域,進而對整個布局層級中需要重繪的部分進行重繪),布局層級越復雜,UI加載的速度就越慢,因此,在撰寫布局的時候,盡可能地扁平化是非常重要的,
AbsoluteLayout已被棄用,咱就不多說它了,FrameLayoutTableLayout有各自的特殊用途,LinearLayout RelativeLayout是可以互換的,ConstraintLayoutRelativeLayout類似,也就是說,在撰寫布局時,可以選擇其中一種,咱們可以以不同的方式來撰寫下面這個簡單的布局,

第一種方式是使用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">
    <View
        android:id="@+id/view_top_1"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@color/color_666666"/>
    <View
        android:id="@+id/view_top_2"
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:background="@color/teal_200"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <View
            android:id="@+id/view_top_3"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@color/color_FF773D"/>
        <View
            android:id="@+id/view_top_4"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@color/purple_500"/>
    </LinearLayout>
</LinearLayout>

LinearLayout視圖層級如下所示:

第二種方法基于RelativeLayout,在這種情況下,你不需要嵌套其他ViewGroup,因為每個子View可以相當于其他View,或相對與父控制元件進行擺放,

<?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">
    <View
        android:id="@+id/view_top_1"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@color/color_666666"/>
    <View
        android:id="@+id/view_top_2"
        android:layout_width="200dp"
        android:layout_below="@id/view_top_1"
        android:layout_height="100dp"
        android:background="@color/teal_200"/>
    <View
        android:id="@+id/view_top_3"
        android:layout_width="100dp"
        android:layout_below="@id/view_top_2"
        android:layout_height="100dp"
        android:background="@color/color_FF773D"/>
    <View
        android:id="@+id/view_top_4"
        android:layout_width="100dp"
        android:layout_below="@id/view_top_2"
        android:layout_toRightOf="@id/view_top_3"
        android:layout_height="100dp"
        android:background="@color/purple_500"/>
</RelativeLayout>

RelativeLayout視圖層級如下所示:

通過兩種方式,可以很容易看出,第一種方式LinearLayout需要3個視圖層級和6個View,第二種方式RelativeLayout僅需要2個視圖層級和5個View,

當然,雖然RelativeLayout效率更高,但不是所有情況都能通過相對布局的方式來完成控制元件擺放,所以通常情況下,這兩種方式需要配合使用,

注意:為了保證應用程式的性能,在創建布局時,需要盡量避免重繪,布局層級應盡可能地扁平化,這樣當View被重繪時,可以減少系統花費的時間,在條件允許的情況下,盡量的使用RelativeLayout和ConstraintLayout,而非LinearLayout,或者用GridLayoutl來替換LinearLayout,

開發者最常使用的是ViewGroup是LinearLayout,只是因為它很容易看懂,撰寫起來簡單,所以它就成了Android開發新手的首選,出于這個原因,Google推出了一個全新的ViewGroup,在適當的時候時候使用它,可以減少冗余,它就是網格布局GridLayout下面文章中也有講到,

布局復用

Android SDK提供了一個非常有用的標簽,在某些情況下,當你希望在其他布局中用一些已存在的布局時,<include/>標簽可通過制定相關參考ID,將一個布局添加到另一個布局,比如自定義一個標題欄,那么可以按照下面的方式,創建一個可重復用的布局檔案,

<?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="wrap_content">
    <View
        android:id="@+id/view_top_1"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@color/color_666666"/>
</RelativeLayout>

接著,將<include/>標簽放入相應的布局檔案中,替換掉對應的View:

<?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">
    <include layout="@layout/include_layout"/>
    <View
        android:id="@+id/view_top_2"
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:background="@color/teal_200"/>
    <View
        android:id="@+id/view_top_3"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/color_FF773D"/>
</RelativeLayout>

這么一來,當你希望重用某些View時,就不用復制/粘貼的方式來實作,只需要定義一個layout檔案,然后通過<include/>參考即可,但是這樣做,可能會引入一個冗余的ViewGroup(重用的布局檔案的根視圖),為此,Android SDK提供了另一個標簽,用來幫我們減少布局冗余,讓層級變得更加扁平化,我們只需要將可重用的根視圖,替換為<merge/>標簽即可,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <View
        android:id="@+id/view_top_1"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@color/color_666666"/>
</merge>

如此一來,就沒有了冗余的視圖控制元件,因為系統會忽略<merge/>標簽,并將<merge/>標簽中的視圖直接放置在相應的布局檔案中,替換<include/>標簽,

使用此標簽時,需要記住它的兩個主要限制,

a、它只能作為布局檔案的跟來使用,

b、每次呼叫LayoutInflater.inflate()時,必須為<merge/>布局檔案提供一個View,作為它的父容器:

LayoutInflater.from(this).inflate(R.layout.merge_layout,parent,true);

一、線性布局(LinearLayout常用)

LinearLayout是一個視圖組,呈線性橫向或縱向,依次繪制每個被添加進來的子組件,

LinearLayout的所有子組件依次堆疊,因此無論子視圖有多寬,垂直串列每行均只有一個子組件,水平串列將只有一行高(最高子組件的高度加上內邊距),LinearLayout會考慮子組件之間的邊距以及每個子組件的對齊方式(右對齊、居中對齊或左對齊),

布局權重

LinearLayout還支持使用android:layout_weight屬性為各個子組件分配權重,此屬性會根據視圖應在螢屏上占據的空間大小,向視圖分配“重要性”值,如果擁有更大的權重值,視圖便可展開,填充父視圖中的任何剩余空間,子組件可指定權重值,然后系統會按照子組件所宣告的權重值比例,為其分配視圖組中的任何剩余空間,默認權重為零,

LinearLayout常用XML屬性和相關方法說明

XML屬性

相關方法

說明

android:baselineAligned

setBaselineAligned(boolean)

設定為 false 時,防止布局對齊其子項的基線,

android:baselineAlignedChildIndex

setBaselineAlignedChildIndex(int)

當線性布局是另一個基線對齊的布局的一部分時,它可以指定基線對齊到其子項中的哪個子項(即,哪個子項 TextView),

android:divider

setDividerDrawable(Drawable)

可繪制用作按鈕之間的垂直分隔線,

android:gravity

setGravity(int)

指定物件應如何在其自身邊界內在 X 軸和 Y 軸上定位其內容,

android:measureWithLargestChild

setMeasureWithLargestChildEnabled
(boolean)

當設定為 true 時,所有有重量的孩子都將被認為是最大孩子的最小尺寸,

android:orientation

setOrientation(int)

布局應該是一列還是一行?對行使用“horizontal”,對列使用“vertical”,

android:weightSum

setWeightSum(float)

定義最大權重總和,

LinearLayout.LayoutParams

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

LinearLayout.LayoutParams常用XML屬性和相關方法說明

XML屬性

相關方法

說明

android:layout_gravity

setGravity(int)

Gravity指定組件應如何放置在其單元組中,

必須是Gravity常量值中的一個或多個(以“|”分隔),

android:layout_weight

指示 LinearLayout 中有多少額外空間分配給

與這些 LayoutParams 關聯的視圖,

Gravity常量(必須使用一個或多個以“|”分隔,如:right|top)

Constant

Value

描述

center

11

將物件放置在其容器的垂直和水平軸的中心,不改變其大小,

center_horizontal

1

將物件放置在其容器的水平中心,不改變其大小,

center_vertical

10

將物件放在其容器的垂直中心,不改變其大小,

clip_horizontal

8

可以設定為將子項的左邊緣和/或右邊緣剪裁到其容器邊界的附加選項,剪輯將基于水平重力:左重力將剪輯右邊緣,右重力將剪輯左邊緣,兩者都不會剪輯兩個邊緣,

clip_vertical

80

可以設定為將子項的頂部和/或底部邊緣剪裁到其容器邊界的附加選項,剪輯將基于垂直重力:頂部重力將剪輯底部邊緣,底部重力將剪輯頂部邊緣,兩者都不會剪輯兩個邊緣,

fill

77

如果需要,增加物件的水平和垂直大小,使其完全填滿其容器,

fill_horizontal

7

如果需要,增加物件的水平尺寸,使其完全填滿其容器,

fill_vertical

70

如果需要,增大物件的垂直尺寸,使其完全填滿其容器,

left

3

將物件推到其容器的左側,不改變其大小,

right

5

將物件推到其容器的右側,不改變其大小,

bottom

50

將物件推到其容器的底部,而不改變其大小,

top

30

將物件推到其容器的頂部,而不改變其大小,

start

800003

將物件推到其容器的開頭,不改變其大小,

end

800005

將物件推到其容器的末端,不改變其大小,

均等分布

如要創建線性布局,讓每個子組件使用大小相同的螢屏空間,請將每個視圖的android:layout_height設定為"0dp"(針對垂直布局),或將每個視圖的android:layout_width設定為"0dp"(針對水平布局),然后,請將每個視圖的android:layout_weight設定為"1",例如:

<?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:id="@+id/ll_top"
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:background="@color/color_188FFF"
        android:orientation="horizontal"
        android:layout_height="0dp">
    </LinearLayout>
    <LinearLayout
        android:id="@+id/ll_bottom"
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:background="@color/color_ff0000"
        android:layout_height="0dp">
    </LinearLayout>
</LinearLayout>

不等分布

你也可創建線性布局,讓子元素使用大小不同的螢屏空間:

a、如果有三個文本欄位,其中兩個宣告權重為 1,另一個未賦予權重,那么沒有權重的第三個文本欄位就不會展開,而僅占據其內容所需的區域,另一方面,另外兩個文本欄位將以同等幅度展開,填充測量三個欄位后仍剩余的空間,

b、如果有三個文本欄位,其中兩個欄位宣告權重為 1,而為第三個欄位賦予權重 2(而非 0),那么現在相當于宣告第三個欄位比另外兩個欄位更為重要,因此,該欄位將獲得總剩余空間的一半,而其他兩個欄位均享余下的空間,

<?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:id="@+id/ll_top"
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:background="@color/color_188FFF"
        android:orientation="horizontal"
        android:layout_height="0dp">
        <View
            android:id="@+id/view_top_1"
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:background="@color/color_ff0000"/>
        <View
            android:id="@+id/view_top_2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/purple_500"/>
        <View
            android:id="@+id/view_top_3"
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:background="@color/color_FF773D"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/ll_bottom"
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:background="@color/color_ff0000"
        android:layout_height="0dp">
        <View
            android:id="@+id/view_bottom_1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/color_FF773D"/>
        <View
            android:id="@+id/view_bottom_2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:background="@color/teal_200"/>
        <View
            android:id="@+id/view_bottom_3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/color_ff0000"/>
    </LinearLayout>
</LinearLayout>

二、相對布局(RelativeLayout常用)

RelativeLayout是一個視圖組,每個子組件位置是相對的,可以相對于同一層級下其他控制元件,也可以相對于父控制元件,

RelativeLayout是用于設計用戶界面的非常強大的實用程式,因為它可以消除嵌套視圖組并保持布局層次結構平坦,從而提高性能,如果你發現自己使用了多個嵌套LinearLayout組,則可以將它們替換為單個RelativeLayout,

定位視圖

RelativeLayout讓子視圖指定它們相對于父視圖或彼此的位置(由 ID 指定),因此,如果A組件的位置是由B組件的位置來決定,Android要求先定義B組件,再定義A組件

RelativeLayout常用XML屬性和相關方法說明

XML屬性

相關方法

說明

android:gravity

setGravity(int)

指定物件應如何在其自身邊界內在X軸和Y軸上定位其內容,

必須是Gravity常量值中的一個或多個(以“|”分隔),

android:ignoreGravity

setIgnoreGravity(int)

指示哪個視圖不應受重力影響,

RelativeLayout.LayoutParams

為了控制RelativeLayout布局容器中各子組件的布局分布,RelativeLayout提供了一個內部類:RelativeLayout.LayoutParams,該類提供了大量的XML屬性來控制RelativeLayout布局容器中子組件的布局分布,

RelativeLayout.LayoutParams里設的XML屬性及說明

XML屬性

說明

android:layout_above

將此視圖的底部邊緣定位在給定的錨視圖 ID 上方,

android:layout_alignBaseline

將此視圖的基線定位在給定錨視圖 ID 的基線上,

android:layout_alignBottom

使此視圖的底部邊緣與給定的錨視圖 ID 的底部邊緣匹配,

android:layout_alignEnd

使此視圖的結束邊緣與給定錨視圖 ID 的結束邊緣匹配,

android:layout_alignLeft

使此視圖的左邊緣與給定錨視圖 ID 的左邊緣匹配,

android:layout_alignParentBottom

如果為 true,則使此視圖的底部邊緣與父視圖的底部邊緣匹配,

android:layout_alignParentEnd

如果為 true,則使此視圖的結束邊緣與父視圖的結束邊緣匹配,

android:layout_alignParentLeft

如果為 true,則使此視圖的左邊緣與父視圖的左邊緣匹配,

android:layout_alignParentRight

如果為 true,則使此視圖的右邊緣與父視圖的右邊緣匹配,

android:layout_alignParentStart

如果為 true,則使此視圖的起始邊緣與父視圖的起始邊緣匹配,

android:layout_alignParentTop

如果為 true,則使此視圖的頂部邊緣與父視圖的頂部邊緣匹配,

android:layout_alignRight

使此視圖的右邊緣與給定錨視圖 ID 的右邊緣匹配,

android:layout_alignStart

使此視圖的起始邊緣與給定錨視圖 ID 的起始邊緣匹配,

android:layout_alignTop

使此視圖的頂部邊緣與給定的錨視圖 ID 的頂部邊緣匹配,

android:layout_alignWithParentIfMissing

如果設定為 true,則在 layout_toLeftOf、layout_toRightOf 等無法找到錨點時,將使用父級作為錨點,

android:layout_below

將此視圖的頂部邊緣定位在給定的錨視圖 ID 下方,

android:layout_centerHorizontal

如果為 true,則此子項在其父項內水平居中,

android:layout_centerInParent

如果為 true,則此子項在其父項內水平和垂直居中,

android:layout_centerVertical

如果為 true,則將此子項垂直居中于其父項內,

android:layout_toEndOf

將此視圖的起始邊緣定位到給定錨視圖 ID 的末尾,

android:layout_toLeftOf

將此視圖的右邊緣定位在給定錨視圖 ID 的左側,

android:layout_toRightOf

將此視圖的左邊緣定位在給定錨視圖 ID 的右側,

android:layout_toStartOf

將此視圖的結束邊緣定位到給定錨視圖 ID 的開始處,

android:layout_above

將此視圖的底部邊緣定位在給定的錨視圖 ID 上方,

除此之外,RelativeLayout.LayoutParams還繼承了ViewGroup.MarginLayoutParams,因此RelativeLayout布局容器中每個子組件也可以指定ViewGroup.MarginLayoutParams所支持的各XML屬性,

不設定相對位置(重疊在一起)

<?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">
    <View
        android:id="@+id/view_top_1"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@color/color_666666"/>
    <View
        android:id="@+id/view_top_2"
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:background="@color/teal_200"/>
    <View
        android:id="@+id/view_top_3"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/color_FF773D"/>
</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">
    <View
        android:id="@+id/view_top_1"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@color/color_666666"/>
    <View
        android:id="@+id/view_top_2"
        android:layout_width="200dp"
        android:layout_below="@id/view_top_1"
        android:layout_height="100dp"
        android:background="@color/teal_200"/>
    <View
        android:id="@+id/view_top_3"
        android:layout_width="100dp"
        android:layout_below="@id/view_top_2"
        android:layout_height="100dp"
        android:background="@color/color_FF773D"/>
    <View
        android:id="@+id/view_top_4"
        android:layout_width="100dp"
        android:layout_below="@id/view_top_2"
        android:layout_toRightOf="@id/view_top_3"
        android:layout_height="100dp"
        android:background="@color/purple_500"/>
</RelativeLayout>

三、網格布局(GridLayout)

GridLayout把這個容器劃分成rows×columns個網格,每個網格可以放一個組件, 除此之外,也可以設定一個組件橫跨多少列、一個組件縱跨多少行(支持跨行和跨列以及每個單元格組內的任意對齊形式),

GridLayout提供了setColumnCount(int)和setRowCount(int)方法來控制該網路的列數和行數,

GridLayout的XML屬性和相關方法說明

XML屬性

相關方法

說明

android:alignmentMode

setAlignmentMode(int)

當設定為 alignMargins 時,會導致在視圖的外邊界之間進行對齊,由其邊距定義,

android:columnCount

setColumnCount(int)

自動定位子項時要創建的最大列數,

android:columnOrderPreserved

setColumnOrderPreserved

(boolean)

設定為 true 時,強制列邊界以與列索引相同的順序出現,

android:orientation

setOrientation(int)

布局期間不使用方向屬性,

android:rowCount

setRowCount(int)

自動定位子項時要創建的最大行數,

android:rowOrderPreserved

setRowOrderPreserved(boolean)

設定為 true 時,強制行邊界以與行索引相同的順序出現,

android:useDefaultMargins

setUseDefaultMargins(boolean)

當設定為 true 時,告訴 GridLayout 在視圖的布局引數中未指定任何邊距時使用默認邊距,

GridLayout.LayoutParams

為了控制GridLayout布局容器中各子組件的布局分布,GridLayout提供了一個內部類:GridLayout.LayoutParams,該類提供了大量的XML屬性來控制GridLayout布局容器中子組件的布局分布,

GridLayout.LayoutParams里設的XML屬性和相關方法說明

XML屬性

相關方法

說明

android:layout_column

界定此視圖占用的單元格組左側的列邊界,

android:layout_columnSpan

列跨度:界定此視圖占用的單元格組的左右邊界之間的差異,

android:layout_columnWeight

在多余空間分配期間應分配給此視圖的水平空間的相對比例,

android:layout_gravity

setGravity(int)

重力指定組件應如何放置在其單元組中,

android:layout_row

界定此視圖占據的單元格組頂部的行邊界,

android:layout_rowSpan

行跨度:界定此視圖占據的單元格組的頂部和底部邊界之間的差異,

android:layout_rowWeight

在多余空間分配期間應分配給此視圖的垂直空間的相對比例,

<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:columnCount="4"
    android:rowCount="5">
    <Button
        android:id="@+id/one"
        android:text="1" />
    <Button
        android:id="@+id/two"
        android:text="2" />
    <Button
        android:id="@+id/three"
        android:text="3" />
    <Button
        android:id="@+id/devide"
        android:text="/" />
    <Button
        android:id="@+id/four"
        android:text="4" />
    <Button
        android:id="@+id/five"
        android:text="5" />
    <Button
        android:id="@+id/six"
        android:text="6" />
    <Button
        android:id="@+id/multiply"
        android:text="×" />
    <Button
        android:id="@+id/seven"
        android:text="7" />
    <Button
        android:id="@+id/eight"
        android:text="8" />
    <Button
        android:id="@+id/nine"
        android:text="9" />
    <Button
        android:id="@+id/minus"
        android:text="-" />
    <Button
        android:id="@+id/zero"
        android:layout_columnSpan="2"
        android:layout_gravity="fill"
        android:text="0" />
    <Button
        android:id="@+id/point"
        android:text="." />
    <Button
        android:id="@+id/plus"
        android:layout_rowSpan="2"
        android:layout_gravity="fill"
        android:text="+" />
    <Button
        android:id="@+id/equal"
        android:layout_columnSpan="3"
        android:layout_gravity="fill"
        android:text="=" />
</GridLayout>

這樣的布局用LinearLayout也能做,但是相對麻煩一點,所以在適當的時候時候使用GridLayout就非常的有必要了,而且你可能注意到了,子組件中并沒有指定android:layout_width和android:layout_height屬性,這是因為這兩個屬性的默認值都是LayoutPrams.WRAP_COUNTENT,而在此,我們希望使用的就是LayoutPrams.WRAP_COUNTENT,所以就沒必要指定了,GridLayout和LinaerLayout十分相似,所以將LinaerLayout替換為GridLayout也相當簡單,

四、表格布局(TableLayout)

TableLayout繼承了LinerarLayout,因此它的本質依然是線性布局管理器,表格采用行、列的形式來管理UI組件,TableLayout并不需要明確地宣告包含多少行、多少列,而是通過TableRow、其他組件來控制表格的行數和列數,

每次向TableLayout中添加TableRow,該TableRow就是一個表格行,TableRow也是容器,因此它也可以不斷的添加其他組件,每添加一個子組件該表格就增加一列,

如果直接向TableLayout添加組件,那么這個組件將直接占一行,

在TableLayout中、列的寬度由該列最寬的那個單元格決定,整個TableLayout的寬度取決于父容器的寬度(默認占滿父容器)

Collapsed:如果某列被設為Collapsed,那么該列所有單元格都會被隱藏,

在TableLayout中,可以為單元格設定的三種行為方式:

Shrinkable:如果某列被設為Shrinkable,那么該列所有單元格的寬度可以被收縮,以保證該變革能適應父容器的寬度,

Stretchable:如果某列被設為Stretchable,那么該列所有單元格的寬度可以被拉伸,以保證組件能完全填充滿表格空余空間,

TableLayout繼承了LinerarLayout,因此它完全可以支持LinerarLayout所支持的XML屬性,初次之外還支持下面的XML屬性,

TableLayout的常用XML屬性和相關方法說明

XML屬性

相關方法

說明

android:collapseColumns

setColumnCollapsed(int,boolean)

要折疊的列的從零開始的索引,

android:shrinkColumns

setShrinkAllColumns(boolean)

要收縮的列的從零開始的索引,

android:stretchColumns

setStretchAllColumns(boolean)

要拉伸的列的從零開始的索引,

<?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:layout_margin="10dp"
    android:orientation="vertical">
    <TableLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:shrinkColumns="1"
        android:stretchColumns="2">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="頂層大佬" />
        <TableRow>
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="不變按鈕" />
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text="收縮按鈕" />

            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text="拉伸按鈕" />
        </TableRow>
    </TableLayout>
    <TableLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:collapseColumns="0"
        android:stretchColumns="2">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="高層大佬" />
        <TableRow>
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="隱藏按鈕" />
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text="不變按鈕" />
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text="拉伸按鈕" />
        </TableRow>
    </TableLayout>
</LinearLayout>

五、幀布局(FrameLayout)

FrameLayout將控制元件以堆疊的形勢堆疊起來,最近添加進去的控制元件繪制在最頂部,FrameLayout為每個加入其中的組件創建一個空白的區域(稱為一幀),每個子組件占據一幀,這些幀都會根據gravity屬性執行自動對齊,

FrameLayout常用的XML屬性和相關方法說明

XML屬性

相關方法

說明

android:foregroundGravity

setForegroundGravity(int)

定義要應用于前景可繪制物件的重力,

android:measureAllChildren

setMeasureAllChildren(boolean)

確定測量時是測量所有子項還是僅測量處于可見或不可見狀態的子項,

FrameLayout包含的子元素也受到FrameLayout.LayoutParams的控制,因此它所包含的子元素也可以指定android:layout_gravity,

<?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">
    <!--依次定義5個View,先定義的在最下面-->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="280dp"
        android:height="280dp"
        android:text="1"
        android:background="@color/color_FF773D"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="240dp"
        android:text="2"
        android:height="240dp"
        android:background="@color/color_188FFF"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="200dp"
        android:text="3"
        android:height="200dp"
        android:background="@color/color_ff0000"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="160dp"
        android:height="160dp"
        android:text="4"
        android:background="@color/teal_700"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="120dp"
        android:height="120dp"
        android:text="5"
        android:background="@color/teal_200"/>
</FrameLayout>

將xml中的幾個android:text=""去掉,通過代碼進行顏色變化,可實作霓虹燈效果,

六、約束布局(ConstraintLayout)

將該庫作為依賴項添加到app/ build.gradle檔案中,

dependencies {
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
// To use constraintlayout in compose
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha06"
}

ConstraintLayout允許您以靈活的方式定位和調整子組件的大小, 它與RelativeLayout類似,所有的視圖都是根據兄弟視圖和父布局之間的關系來布局的,但是它比RelativeLayout更靈活,并且更易于在Android Studio的布局編輯器中使用,

ConstraintLayout的所有功能都可以直接從布局編輯器的可視化工具中使用,因為布局API和布局編輯器是專門為對方構建的, 所以你可以使用ConstraintLayout完全通過拖放操作來構建你的布局,而不是編輯XML,

請注意,約束中不能有回圈依賴,

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#11ff0000">
    <TextView
        android:id="@+id/tv1"
        android:layout_width="140dp"
        android:layout_height="86dp"
        android:layout_marginStart="12dp"
        android:layout_marginTop="12dp"
        android:background="#617"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/tv2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="12dp"
        android:text="就現在經濟大環境而言,很不樂觀,程式員的日子也很不好過"
        android:textColor="#000000"
        android:textSize="16dp"
        app:layout_constraintLeft_toRightOf="@id/tv1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@id/tv1" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="12dp"
        android:text="3分鐘前"
        android:textColor="#333"
        android:textSize="12dp"
        app:layout_constraintBottom_toBottomOf="@id/tv1"
        app:layout_constraintLeft_toRightOf="@id/tv1" />
</androidx.constraintlayout.widget.ConstraintLayout>

tv1設定了://父布局的左上角

app:layout_constraintLeft_toLeftOf="parent"

app:layout_constraintTop_toTopOf="parent"

tv2設定了:tv2在tv1的右側,tv2的右側和父布局對其,tv2和tv1頂部對齊;

app:layout_constraintLeft_toRightOf="@id/tv1",

app:layout_constraintRight_toRightOf="parent"

app:layout_constraintTop_toTopOf="@id/tv1"

tv3設定了:tv3在tv1的右側,tv3和tv1底部對其,

app:layout_constraintLeft_toRightOf="@id/tv1"

app:layout_constraintBottom_toBottomOf="@id/tv1"

相對定位

相對定位是在 ConstraintLayout 中創建布局的基本構建塊之一,這些約束允許您相對于另一個小部件定位給定的小部件,您可以在水平和垂直軸上約束小部件:

水平軸:左、右、起點和終點

垂直軸:頂邊、底邊和文本基線

一般概念是將小部件的給定一側約束到任何其他小部件的另一側,

以下是可用約束的串列:

layout_constraintLeft_toLeftOf

layout_constraintLeft_toRightOf

layout_constraintRight_toLeftOf

layout_constraintRight_toRightOf

layout_constraintTop_toTopOf

layout_constraintTop_toBottomOf

layout_constraintBottom_toTopOf

layout_constraintBottom_toBottomOf

layout_constraintBaseline_toBaselineOf

layout_constraintStart_toEndOf

layout_constraintStart_toStartOf

layout_constraintEnd_toStartOf

layout_constraintEnd_toEndOf

邊距

如果設定了邊距,它們將應用于相應的約束(如果存在),將邊距強制為目標邊和源邊之間的空間,通常的布局邊距屬性可用于此效果:

android:layout_marginStart

android:layout_marginEnd

android:layout_marginLeft

android:layout_marginTop

android:layout_marginRight

android:layout_marginBottom

請注意,邊距只能為正數或等于零,并且需要一個Dimension.

連接到 GONE 小部件時的邊距

當位置約束目標的可見性為 時View.GONE,您還可以使用以下屬性指示要使用的不同邊距值:

layout_goneMarginStart

layout_goneMarginEnd

layout_goneMarginLeft

layout_goneMarginTop

layout_goneMarginRight

layout_goneMarginBottom

尺寸限制

您可以為ConstraintLayout自身定義最小和最大尺寸:

android:minWidth 設定布局的最小寬度

android:minHeight 設定布局的最小高度

android:maxWidth 設定布局的最大寬度

android:maxHeight 設定布局的最大高度

、絕對布局(AbsoluteLayout)

因為靈活性太差,在API Level 3中被廢棄,在實際使用中你需要為所有子組件指定x,y坐標,它的直接子類是WebView,

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/286409.html

標籤:其他

上一篇:由淺入深學習android input系統(二) - input事件如何傳遞到app行程( InputDispatcher )

下一篇:fw問題修改

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more