[Android步步為營]第4營 布局管理器Layout


在前面幾講中, 我們其實已經多次用到過Layout,用的最多的線性布局。今天我們來詳細探討一下布局。

Layout,是在Activity的界面的結構,它定義了您的UI元素該如何組織來呈現給用戶。Layout的定義其實有兩種方式:

  • Xml定義
  • 代碼定義

Xml layout 定義的好處在於,減少了與代碼的耦合,同一份代碼可以用不同layout以適應大小屏幕,橫豎屏。

代碼定義好的好處在於靈活性強,當然效率也相對要一些。

所以這兩種方式有很有用,有時也會結合起來使用。但平常用的最多的還是xml形式的。

主要的Layout一共有五種:

  • LinearLayout 線性布局
  • RelativeLayout 相對布局
  • AbsoluteLayout 絕對定位,以絕對坐標來定位,已經被廢棄,因為Android平台的設備屏幕如此眾多,用絕對定位非常不合適。
  • FrameLayout 幀布局
  • TableLayout 表格布局

Android 3.0引入的還有Fragment, 嚴格來講它並不是layout,以后會詳細描述。

下面我們來詳細研究一下這幾種Layout:

LinearLayout

包括Vertical垂直, Horizontal水平兩種,由屬性android:orientation設定,這個在上一講已經講過,這里不在重復。

線性布局還有一個重要的屬性weight. 我們先來看一個例子:

我們有三個按鈕,水平放置:

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

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="收藏" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="下載" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="分享" />

</LinearLayout>

預覽結果是:

7MAU605IHPH2(Y9A52L$UF5

實際上這樣不大好看,我們希望他們都居中,而且平分水平方向的空間,於是我們為每一個Button 加上android:layout_weight屬性,值都是1,表示他們的權重都是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="wrap_content"
    android:orientation="horizontal" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="收藏" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="下載" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="分享" />

</LinearLayout>

預覽結果:

89X)WH4WC%0)4$25V$575}2所以當元素的layout_weight值都是一樣時,他們會平分長度(horizontal時)或者高度(vertical時)。

接下來我們做一下別的嘗試:

把兩邊的Button的layout_weight屬性去掉呢?

15(B3{IUEKZIUM5}}9_DA(Y這個時候只有中間的Button有layout_weight=1, 把它的值調大點? 2? 3?。。。10?發現結果都是一樣的。所以:

LinearLayout下的子元素,1. 默認情況下layout_weight為零 2.所有的子元素當中,layout_weight值最大的那個元素,會占滿剩下的所有空間

LinearLayout中還有一個重要的屬性android:weightSum 總權重值

還是這個例子,假如我們想讓兩邊的按鈕占四分之一,中間按鈕占四分之二, 可以這樣來實現:

LinearLayout的android:weightSum=”4”, 兩邊的Button layout_weight=”1”, 中間的為2,結果如下:

T_ZET%YL3Q2T60)C_70]${F

你也許注意到,既然已經有了layout_weight來分配寬度(horizontal時),layout_width的值還有意義嗎?

確實,沒有意義了,但是它又是必須要寫的屬性,所以,為了提高性能,我們可以把它寫成android_width=”0dp”.

<Button
        android:id="@+id/button3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="分享" />

RelativeLayout

相對布局,是通過UI元素的相互參照來定位,如下圖,A,B,D在C的下面,而且D在A的右邊,也在B的左邊。

`J@9(Y5(TT7YO4NN0MOHKFX

相對布局非常有用,它可是實現許多復雜要求的界面布局。

 

相對布局有如下重要屬性:

在某個元素的上下左右方,值為對應元素的id

android:layout_toLeftOf
android:layout_toRightOf
android:layout_above 

android:layout_below

讓本元素的邊緣與指定id的上下左右,基線邊緣對齊,值都是某個元素的Id

android:layout_alignBaseline

android:layout_alignTop

android:layout_alignBottom
android:layout_alignLeft

android:layout_alignRight

 

以下的值為true時,靠在父容器的上下左右邊緣

android:layout_alignParentBottom
android:layout_alignParentLeft
android:layout_alignParentRight
android:layout_alignParentTop
android:layout_centerHorizontal
android:layout_centerInParent
android:layout_centerVertical

 

android:layout_alignWithParentIfMissing

如果設置為true, 被依賴的View, 如果設置成了Gone(View 有個可見性屬性android:visibility, 可選三個值visible, invisible, gone), 將以其父容器作為參考。
 

舉一個實例,就容易明白了:

M3F}J3FYU6B{EXWERF9@QZJ

要求:

  • 文本框和兩個按鈕靠界面底部,他們都是同一行。
  • 兩個按鈕靠右排列
  • 文本框靠左
  • 圖片在文本框的上方
<?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" >
    
    <!-- android:layout_above, 在EditText 的上方 -->
    <ImageView
        android:id="@+id/top_image"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/et_reply"
        android:layout_marginBottom="10dp"
        android:src="@drawable/cat" />
    <!-- android:layout_alignParentLeft,android:layout_alignParentBottom 靠左在界面底部 -->    
    <EditText
        android:id="@+id/et_reply"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="10dp"
        android:ems="8"
        android:hint="留言..." />
 <!-- layout_toLeftOf在btn_renren的右邊,layout_alignBottom與et_reply的底部邊緣對齊 -->    
    <ImageButton
        android:id="@+id/btn_kaixin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@+id/btn_renren"
        android:layout_alignBottom="@id/et_reply"
        android:src="@drawable/ic_chk_kaixin_selected" />

    <ImageButton
        android:id="@+id/btn_renren"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/et_reply"
        android:layout_alignParentRight="true"
        android:src="@drawable/ic_chk_renren_selected" />
</RelativeLayout>

 

需要注意的是,填寫參考的id時,有時候是@id/xxx, 有時候是@+id/xxxx, 怎么分辨什么時候該用啥呢?

當依賴的元素在當前元素的后面(XML節點出現的順序),用@+id/xxxx,因為還沒有出現,所有要用@+id表示新建id

反之,在前面,用@id/xxxx, @id表示引用已有id

FrameLayout

布局當中的元素可以重疊在一起,元素出現的順序很重要,后面的元素會覆蓋前面的。

 

~)R3OL2YT1169AXB5H5DEQL

<?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" >
    <TextView
        android:id="@+id/tv1"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:gravity="bottom|right"
        android:text="First"
        android:textSize="40sp"
        android:background="#ffabff00" />
    <TextView
        android:id="@+id/tv2"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:gravity="bottom|right"
        android:text="Second"
        android:textSize="40sp"
        android:background="#ff8432" />
     <TextView
        android:id="@+id/tv3"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:gravity="bottom|right"
        android:text="Third"
        android:textSize="40sp"
        android:background="#0f0fff" />   
</FrameLayout>

我們可以看到,FrameLayout里面的元素默認都是以左上角為對齊的。

這個FrameLayout可能有個Bug, 設置android:layout_margin時不生效,但是如果先設置了android:layout_gravity, layout_margin又生效了。

TableLayout

表格的方式來排列元素。

<?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:stretchColumns="0,1,2" >

    <TableRow
        android:id="@+id/tableRow1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

        <ImageView
            android:id="@+id/top_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pic1" />

        <ImageView
            android:id="@+id/top_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pic2" />

        <ImageView
            android:id="@+id/top_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pic3" />
    </TableRow>

    <TableRow
        android:id="@+id/tableRow2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp" >

        <ImageView
            android:id="@+id/top_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pic4" />

        <ImageView
            android:id="@+id/top_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pic5" />

        <ImageView
            android:id="@+id/top_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pic6" />
    </TableRow>

</TableLayout>

5~[{4W%`3OIHDDMH@`2)U(Y

TableLayout屬性有:

android:collapseColumns:以第0行為序,隱藏指定的列

如果android:collapseColumns=2,結果是:

_H@@DA7(DI6}@$O85_{P[VB中間一列被隱藏了。

android:shrinkColumns:以第0行為序,當行寬不夠包裹內容時,自動“縮水”指定的列

注意是“縮水”,我們先把最后一張換上大一點的圖片,讓它不夠位置,

S%DM_IRE3QH[N_Y_Q}DRO(W

如果android:shrinkColumns=2, 縮水最后一列,結果是:

{BKB)@__A$9A85IEGVIW%I8

如果android:shrinkColumns=1,縮水中間一列:

}NA_B{ZOE7MNPI6HB(TKKX9因為最后一張圖太大了,中間一列直接“縮水”到不見了。

android:stretchColumns:以第0行為序,盡量把指定的列填充空白部分,注意是“空白部分”。第一個例子就是android:stretchColumns="0,1,2"

下一講,我們來用代碼定義Layout.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM