Android UI詳解之佈局管理器(一)

                                                                Android UI詳解之佈局管理器

一、佈局管理器

             ①頂級父類View

             ②子類GroupView

             ③AbsoluteLayout、FrameLayout、LinearLayout、GridLayout、RelativeLayout

             ④TableLayout 、TabWidget繼承LinearLayout


   2、在分析佈局之前,我們首先看看控件:Android中任何可視化的控件都是從android.veiw.View繼承而來的,系統提供了兩種方法來設置視圖:第一種也是我們最常用的的使用XML文件來配置View的相關屬性,然後在程序啓動時系統根據配置文件來創建相應的View視圖。第二種是我們在代碼中直接使用相應的類來創建視圖。

      如何使用XML文件定義視圖:

      每個Android項目的源碼目錄下都有個res/layout目錄,這個目錄就是用來存放佈局文件的。佈局文件一般以對應activity的名字命名,以 .xml 爲後綴。在xml中爲創建組件時,需要爲組件指定id,如:android:id="@+id/名字"系統會自動在gen目錄下創建相應的R資源類變量。 

    如何在代碼中使用視圖:   

      在代碼中創建每個Activity時,一般是在onCreate()方法中,調用setContentView()來加載指定的xml佈局文件,然後就可以通過findViewById()來獲得在佈局文件中創建的相應id的控件了,如Button等

       下面我們來介紹Android系統中爲我們提供的五大布局:LinearLayout(線性佈局)、FrameLayout(單幀佈局)、AbsoluteLayout(絕對佈局)、TablelLayout(表格佈局)、RelativeLayout(相對佈局)。其中最常用的的是LinearLayout、TablelLayout和RelativeLayout。這些佈局都可以嵌套使用。


(1)LinearLayout 線性佈局

  線性佈局是按照水平或垂直的順序將子元素(可以是控件或佈局)依次按照順序排列,每一個元素都位於前面一個元素之後。線性佈局分爲兩種:水平方向和垂直方向的佈局。分別通過屬性android:orientation="vertical" 和 android:orientation="horizontal"來設置。

 android:layout_weight 表示子元素佔據的空間大小的比例,有人說這個值大小和佔據空間成正比,有人說反比。我在實際應用中設置和網上資料顯示的剛好相反,這個問題後面會專門寫一篇文章來分析。現在我們只需要按照正比例來設置就可以。 

例如下面我們實現一個如圖所示的簡易計算器界面:

                                                     

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"
    tools:context=".MainActivity" >

  // 這裏第一行顯示標籤爲一個水平佈局
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <EditText
            android:id="@+id/msg"
            android:inputType="number"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="">
        </EditText>    
    </LinearLayout>
    
  // 第二行爲 mc m+ m- mr 四個Button構成一個水平佈局
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
     	<Button
     	    android:layout_width="match_parent"
     	    android:layout_height="wrap_content"
     	    android:text="mc" android:layout_weight="1">
     	</Button>
     	<Button
     	    android:layout_width="match_parent"
     	    android:layout_height="wrap_content"
     	    android:text="m+" android:layout_weight="1">
     	</Button>
     	<Button
     	    android:layout_width="match_parent"
     	    android:layout_height="wrap_content"
     	    android:text="m-" android:layout_weight="1">
     	</Button>
     	<Button
     	    android:layout_width="match_parent"
     	    android:layout_height="wrap_content"
     	    android:text="mr" android:layout_weight="1">
     	</Button>
  </LinearLayout>
    
  // 同上 C +/-  / * 四個Button構成一個水平佈局
      <LinearLayout
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:orientation="horizontal" >
          <Button
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_weight="1"
              android:text="C" >
          </Button>
          <Button
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_weight="1"
              android:text="+/-" >
          </Button>
          <Button
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_weight="1"
              android:text="/" >
          </Button>
          <Button
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_weight="1"
              android:text="*" >
          </Button>
      </LinearLayout>
    
      <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
     	<Button
     	    android:layout_width="match_parent"
     	    android:layout_height="wrap_content"
     	    android:text="7" android:layout_weight="1">
     	</Button>
     	<Button
     	    android:layout_width="match_parent"
     	    android:layout_height="wrap_content"
     	    android:text="8" android:layout_weight="1">
     	</Button>
     	<Button
     	    android:layout_width="match_parent"
     	    android:layout_height="wrap_content"
     	    android:text="9" android:layout_weight="1">
     	</Button>
     	<Button
     	    android:layout_width="match_parent"
     	    android:layout_height="wrap_content"
     	    android:text="-" android:layout_weight="1">
     	</Button>
  </LinearLayout>
  
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="4" >
        </Button>
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="5" >
        </Button>
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="6" >
        </Button>
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="+" >
        </Button>
    </LinearLayout>
    
  // 最外層是一個水平佈局,由左邊上面一行1 2 3三個Button,下面一行的0 . 兩個Button 和 右邊的=構成
     <LinearLayout android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    // 這裏 1 2 3 和 下面的 0 . 構成一個垂直佈局
        <LinearLayout android:orientation="vertical"
        	android:layout_weight="3"
        	android:layout_width="wrap_content"
        	android:layout_height="wrap_content">
      // 這裏的 1 2 3 構成一個水平佈局
     		<LinearLayout android:orientation="horizontal"
        		android:layout_width="match_parent"
        		android:layout_height="wrap_content">
        		<Button
        		    android:layout_width="wrap_content"
        		    android:layout_height="wrap_content"
        		    android:layout_weight="1"
        		    android:text="1"></Button>
        		<Button
        		    android:layout_width="wrap_content"
        		    android:layout_height="wrap_content"
        		    android:layout_weight="1"
        		    android:text="2"></Button>
        		<Button
        		    android:layout_width="wrap_content"
        		    android:layout_height="wrap_content"
        		    android:layout_weight="1"
        		    android:text="3"></Button>
     		</LinearLayout>
      // 這裏的 0 和 . 構成一個水平佈局,注意這裏的android_weight參數設置
     		<LinearLayout android:orientation="horizontal"
        		android:layout_width="match_parent"
        		android:layout_height="wrap_content">
        		<Button
        		    android:layout_width="0px"
        		    android:layout_height="wrap_content"
        		    android:layout_weight="2"
        		    android:text="0"></Button>
        		<Button
        		    android:layout_width="0px"
        		    android:layout_height="wrap_content"
        		    android:layout_weight="1"
        		    android:text="."></Button>
        	</LinearLayout>	
     	</LinearLayout>
    // 這裏一個單獨Button構成的垂直佈局
    <LinearLayout android:orientation="vertical"
        android:layout_weight="1"
        	android:layout_width="wrap_content"
        	android:layout_height="match_parent">
     		<Button
     		    android:layout_width="match_parent"
     		    android:layout_height="match_parent"
        android:text="="></Button>
      </LinearLayout>
     </LinearLayout>   

</LinearLayout>


(2)TableLayout 表格佈局

         表格佈局,適用於多行多列的佈局格式,每個TableLayout是由多個TableRow組成,一個TableRow就表示TableLayout中的每一行,這一行可以由多個子元素組成。實際上TableLayout和TableRow都是LineLayout線性佈局的子類。但是TableRow的參數android:orientation屬性值固定爲horizontal,且android:layout_width=MATCH_PARENT,android:layout_height=WRAP_CONTENT。所以TableRow實際是一個橫向的線性佈局,且所以子元素寬度和高度一致。

       注意:在TableLayout中,單元格可以爲空,但是不能跨列,意思是隻能不能有相鄰的單元格爲空。

        在TableLayout佈局中,一列的寬度由該列中最寬的那個單元格指定,而該表格的寬度由父容器指定。可以爲每一列設置以下屬性:

     Shrinkable  表示該列的寬度可以進行收縮,以使表格能夠適應父容器的大小

     Stretchable 表示該列的寬度可以進行拉伸,以使能夠填滿表格中的空閒空間

     Collapsed  表示該列會被隱藏

TableLayout中的特有屬性:

        android:collapseColumns

        android:shrinkColumns ="0,1,2,3" // 表示 4列都可以收縮,就是當有多列時,如果不設置此項會出現溢出屏幕,不會收縮

        android:stretchColumns = "0,1,2,3" // 表示 4列都可以拉伸,就是當只有少量按鈕,默認寬度不能佔滿一橫屏,就需要拉伸。

Demo 1     

      這個對應的xml

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"    
    android:shrinkColumns="0,1,2,3,4,5"
    android:stretchColumns="0,1,2,3,4,5"    
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >    

    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button1">
        </Button>
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button2">
        </Button>
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button2">
        </Button>
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button2">
        </Button>
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button2">
        </Button>
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button3">
        </Button>
    </TableRow>
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button4">
        </Button>
      
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button5">
        </Button>
    </TableRow>

</TableLayout>
 



Demo 2 隱藏兩列

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"    
    android:collapseColumns="0,1"
    android:shrinkColumns="0,1,2,3,4,5"
    android:stretchColumns="0,1,2,3,4,5"    
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >    

    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button1">
        </Button>
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button2">
        </Button>
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button2">
        </Button>
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button2">
        </Button>
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button2">
        </Button>
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button3">
        </Button>
    </TableRow>
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button4">
        </Button>
      
        <Button android:gravity="center"
            android:padding="10dp"
            android:text="Button5">
        </Button>
    </TableRow>

</TableLayout>




(3)RelativeLayout 相對佈局

   RelativeLayout繼承於android.widget.ViewGroup,其按照子元素之間的位置關係完成佈局的,作爲Android系統五大布局中最靈活也是最常用的一種佈局方式,非常適合於一些比較複雜的界面設計。

   注意:在引用其他子元素之前,引用的ID必須已經存在,否則將出現異常。

常用的位置屬性:

android:layout_toLeftOf 	      該組件位於引用組件的左方
  android:layout_toRightOf 		該組件位於引用組件的右方
  android:layout_above 			該組件位於引用組件的上方
  android:layout_below 		    	該組件位於引用組件的下方
  android:layout_alignParentLeft  	該組件是否對齊父組件的左端   
  android:layout_alignParentRight 	該組件是否齊其父組件的右端
  android:layout_alignParentTop   	該組件是否對齊父組件的頂部
  android:layout_alignParentBottom  	該組件是否對齊父組件的底部
  android:layout_centerInParent 	該組件是否相對於父組件居中
  android:layout_centerHorizontal   	該組件是否橫向居中
  android:layout_centerVertical 	該組件是否垂直居中

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <Button android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Button1"
        ></Button>
    <Button android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/btn1"
        android:layout_above="@id/btn1"
        android:text="Button2"
        ></Button>
    <Button android:id="@+id/btn3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/btn1"
        android:layout_above="@id/btn1"
        android:text="Button3"
        ></Button>
    <Button android:id="@+id/btn4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/btn2"
        android:layout_toLeftOf="@id/btn3"
        android:layout_above="@id/btn2"
        android:text="Button4"
        ></Button>
</RelativeLayout>

android:layout_centerHorizontal:true用於相對佈局(RelativeLayout)的子控件居中。
    android:gravity="center"用於控件裏的內容怎麼顯示 


(4)FrameLayout 框架佈局

 

FrameLayout是最簡單的佈局了。所有放在佈局裏的控件,都按照層次堆疊在屏幕的左上角。後加進來的控件覆蓋前面的控件。

在FrameLayout佈局裏,定義任何空間的位置相關的屬性都毫無意義。控件自動的堆放在左上角,根本不聽你的控制。

看以下的例子:

 

第四層"/>

</FrameLayout>

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    >

<TextView  

    android:layout_width="fill_parent" 

    android:layout_height="wrap_content"

    android:textSize="50dip"

    android:textColor="#ffffff"

    android:text="第一層"/>

<TextView  

    android:layout_width="fill_parent" 

    android:layout_height="wrap_content" 

    android:textSize="40dip"

    android:textColor="#ffff00"

    android:text="第二層"/>

<TextView  

    android:layout_width="fill_parent" 

    android:layout_height="wrap_content" 

    android:textSize="30dip"

    android:textColor="#ff00ff"

    android:text="第三層"/>

<TextView  

    android:layout_width="fill_parent" 

    android:layout_height="wrap_content" 

    android:textSize="20dip"

    android:textColor="#00ffff"

    android:text="第四層"/>


 

 效果都是從左上腳開始排列 

變化1

我們現在來嘗試改變一下他們的位置。把第一個和第二個文本框改成:

<TextView 

    android:id="@+id/tv1"

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:textSize="50dip"

    android:textColor="#ffffff"

    android:text="第一層"/>

<TextView 

    android:id="@+id/tv2"

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:textSize="40dip"

    android:textColor="#ffff00"

android:layout_toRightOf="@id/tv1"

android:text="第二層"/>

也就是說,讓第二個文本框放在第一個文本框的右邊。我們來看看效果。看到了沒?還是一樣的不變吧。

變化2

我們來嘗試下android:gravity屬性。把第三個文本框改成:

<TextView 

    android:id="@+id/tv3"

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:textSize="30dip"

    android:textColor="#ff00ff"

    android:gravity="right"

android:text="第三層"/>

看看效果如何?會發現 ,竟然沒有覆蓋,而是錯開了!!!

 

首先呢,我們不要大驚小怪。這個現象並不說明FrameLayout失效了。gravity屬性,是控制控件內部文本的格式的。而我們看我們控件的寬的屬性是什麼?是“fill_parent”,也就是說,我們文本框的寬度就是屏幕的寬度。那麼android:gravity="right"文本靠右,而文本框本身還是左上堆疊在一起的。不信,我們再來改改:

<TextView 

    android:id="@+id/tv3"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:textSize="30dip"

    android:textColor="#ff00ff"

    android:gravity="right"

android:text="第三層"/>

我們讓第三個文本框的寬度自適應,也就是保證顯示全文字即可。這個時候看一下效果呢?是不是打回原形啦?哈哈哈。

變化3

我們再來試試” android:layout_centerVertical”屬性。把第四個文本框改成:

<TextView 

    android:id="@+id/tv4"

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:textSize="20dip"

    android:textColor="#00ffff"

    android:layout_centerVertical="true"

android:text="第四層"/>

效果如何?沒任何效果!

 

總結一下,經過以上的3個實驗,我們知道FrameLayout根本無法控制他的子控件的位置。所有的控件都是左上對其。但是控件本身是可以控制自己內部的佈局的。所以利用透明,也是可以完成一些簡單的功能的。例如屏幕四個角各顯示一些文字(是顯示文字,沒法放置控件)。因爲每一層覆蓋下一層的時候,如果用透明背景,則下一層不會被背景覆蓋。

什麼是透明背景?這個……說來話長啦。偷個懶,下次寫一下透明的處理。

是不是有人會問,這麼簡單的Layout有什麼用?我想還是有它存在的價值的。

當你需要自己寫一個View的時候,在View裏面已經完成了你的邏輯(例如遊戲^_^),那麼這個View只需要一個容器放置,就可以使用FrameLayout了。雖然用其他的佈局也可以,但是用最簡單的不是更省系統資源麼。

 

(5) AbsoluteLayou 絕對佈局

   絕對佈局中將所有的子元素通過設置android:layout_x 和 android:layout_y屬性,將子元素的座標位置固定下來,即座標(android:layout_x, android:layout_y) ,layout_x用來表示橫座標,layout_y用來表示縱座標。 屏幕左上角爲座標(0,0),橫向往右爲正方,縱向往下爲正方。實際應用中,這種佈局用的比較少,因爲Android終端一般機型比較多,各自的屏幕大小。分辨率等可能都不一樣,如果用絕對佈局,可能導致在有的終端上顯示不全等。

除上面講過之外常用的幾個佈局的屬性: 
(1)layout_margin    用於設置控件邊緣相對於父控件的邊距 
android:layout_marginLeft  
android:layout_marginRight 
android:layout_marginTop 
android:layout_marginBottom 

(2) layout_padding  
用於設置控件內容相對於控件邊緣的邊距 
android:layout_paddingLeft 
android:layout_paddingRight 
android:layout_paddingTop 
android:layout_paddingBottom 

(3) layout_width/height 
用於設置控件的高度和寬度 
wrap_content 內容包裹,表示這個控件的裏面文字大小填充 
fill_parent 跟隨父窗口 
match_parent 和fill_parent 一樣,
(4)

基中的android:layout_width和android:width的區別:

  • android:layout_width 只有兩種選擇一個是fill_parent ,二是wrap_content
  • android:width 這個是用來view的具體寬度的,以像素爲單位。

android:width 支持

  • px (pixels)像素
  • dip (device independent pixels)設備獨立像素
  • sp (scaled pixels ― best for text size)放大像素--對文本大小最好
  • pt (points) 點
  • in (inches)英寸
  • mm (millimeters)毫米

  • 如果view中有layout_width屬性的話,不管有沒有width屬性,該view的形狀是由父容器

(5) gravity  
用於設置View組件裏面內容對齊方式 
top bottom left   right  center等 

(6) android:layout_gravity   
用於設置Container組件的對齊方式 
android:layout_alignTop 本元素的上邊緣和某元素的的上邊緣對齊 
android:layout_alignLeft 本元素的左邊緣和某元素的的左邊緣對齊 
android:layout_alignBottom 本元素的下邊緣和某元素的的下邊緣對齊 

android:layout_alignRight 本元素的右邊緣和某元素的的右邊緣對齊 



發佈了34 篇原創文章 · 獲贊 6 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章