Android學習筆記3-介面
使用者介面
在一個Android應用程式裡,使用者介面是一系列的View和ViewGroup物件組合而成。Android有很多種View和ViewGroup物件,他們都繼承自View基類。
View物件是Android平臺使用者介面的基本物件。這些view類作為與使用者互動的widgets小部件的父類,像文字框和按鈕。ViewGroup作為提供各種佈局結構的layouts的父類,例如linear線性佈局,表格佈局和絕對佈局。
一個view物件是一個數據結構,他儲存佈局引數和螢幕特定區矩形區域的內容。一個view會處理自己所在螢幕區域的測量、佈局、繪製、焦點改變、滾動、和按鍵手勢互動。作為使用者互動物件,一個view可以作為使用者與系統的互動工具,接收事件。
View 結構體系
在Android平臺,你要用到View或ViewGroup的層、節點的方式來定義一個Android使用者介面,就像下面的圖表,這個層次結構樹可以按你的需求變得簡單或者複雜。你可以用Android系統已經定義好的小控制元件或者佈局,或者自定義一些。
為了能讓你的view層次結構在螢幕上渲染,你的activity需要呼叫setContentView()方法並且傳遞一個根節點物件的引用。Android系統接收這些配置,並使用他們來進行測量繪製這個樹形的檢視結構。這個檢視結構的根節點要求他的孩子節點自我繪製,反過來說,每個viewGroup節點負責讓他們的子節點自我繪製。子節點會在父節點哪裡請求到尺寸和位置,但父物件會最終決定他們孩子有多大。Android按順序解析你的佈局上的所有元素,從頂端開始,例項化view並且把他們新增到父物件。因為他們都是按順序被繪製的,如果某些view超出的顯示範圍,那麼後來繪製的將會覆蓋原來的。
關於view結構體系怎樣繪製,在後面會有詳細的討論。
佈局
通常最多的佈局是通過xml來定義。xml提供一個容易閱讀的結構,很像html。xml中每個元素都是一個view或者viewGroup物件(或他們的子類)。view在樹結構中是葉子節點,ViewGroup物件在非葉子節點(樹枝節點,參考上圖)。
xml元素名代表著各個類。比如<TextView>元素會建立一個TextView控制元件,一個<LinearLayout>會建立一個LinearLayout的viewGroup,當你載入一個佈局資源,Android系統會初始化執行時物件,即對應的佈局元素。
例如,一個簡單的垂直佈局,裡面包含一個textView和一個Button。
[xhtml] view plain copy
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <TextView android:id="@+id/text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Hello, I am a TextView" />
- <Button android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Hello, I am a Button" />
- </LinearLayout>
注意,linearLayout元素包含著TextView和Button。你可以巢狀另外的LinearLayout,來增加view的長度,或者增加一個更復雜的佈局。
更多關於UI佈局的資訊,請參考 Declaring Layout章節。
你可以在你的佈局裡用很多種佈局方式,使用很多不同型別的viewGroup,你可以定義無限多的子view或者子viewGroup。android提供一些預先定義好的佈局,包括:LinearLayout-線性佈局, RelativeLayout-關係佈局, TableLayout-表格佈局, GridLayout 網格佈局等。他們提供一些獨特的引數用來定義view的位置和佈局結構。
Widgets小部件
widget是一個服務於使用者與介面互動的view物件。Android提供很多檢視小部件,如按鈕、尋則狂、文字輸入框、到呢個,你可以很快的構建自己的佈局。一些小部件很複雜,像日期選擇器,一個時鐘,縮放控制。但你不會被Android平臺所提供的UI部件所限制,你可以自定義UI部件,可以繼承或者結合已經存在的UI部件。
UI事件
一旦你向介面添加了view或者widget,你可能會想他們怎樣與使用者進行互動的,這樣你就可以執行一些操作。新增UI事件,你需要做兩件事情:
@ 定義事件監聽器並註冊給view。
多半情況下,這就是你怎樣監聽事件:view 類包含了一些名如OnXXXListener的監聽器,他們都有名為OnXXX()的回撥方法。例如:View.onClickListener(這是處理點選事件的),View.onTouchListener(處理觸控事件),View
.onKeyListener(處理按鍵事件),所以如果你想讓view響應點選事件,比如按鈕被選中,你需要實現OnClickListener介面並且定義回撥方法,並且用setOnClickListener()方法來註冊View。
@ 覆蓋一個已經存在的回撥方法:
如果你失信了自己的View類並且想要監聽一些特殊的事件,那你應該用這種方法。例如,你可以處理螢幕觸控事件,處理滾動球事件,按鍵等事件。它允許你定義預設的事件,即自定義的view的每個事件,確定這個時間是否會傳遞到一些字view。然後,他們呼叫view類的回撥函式,所以當你自定義一個元件時才有機會用到這種方法。
選單Menu
應用程式選單是UI的另一個很重要的部分。Menu提供一些可靠的藉口來展示程式的功能和一些設定。通常menu是通過按menu鍵才顯示的。然而,你可以讓使用者按下或者按住某一項時顯示menu選單。
menu選單也遵循view的層次結構,但不要自己定義。取而代之的是,你只需為你的activity定義onCreateOptionsMenu()和onCreateContextMenu()兩個回撥方法即可,在適當的時間,Android會自動的繪製必要的檢視結構並且menu的所包含的子項的。
Menu會處理他自己的時間。所以不需要註冊事件監聽器,當menu中的某一項被選中,系統會呼叫onOptionsItemSelected()方法或者onContextItemSelected()方法。
和應用程式的佈局很像,你可以用xml來配置你的menu項。
高階特徵
一旦你瞭解了建立使用者介面的基本原則。你可以瀏覽一些高階特徵來建立更復雜的應用程式介面。
介面卡Adapters
一些時候,你不想用“硬程式碼”來填充一些view的資料,相反,你想讓view繫結額外的資料集。要這樣的話,你要定義一個AdapterView,每個子View裡的資料都會被介面卡填充。
介面卡檢視物件 AdapterView是實現的ViewGroup介面,子類是由被給出的介面卡物件決定的。介面卡就像你的adapter檢視和資料來源之間的介面卡。這裡有幾種介面卡類的實現方式,對於特殊的任務,例如自定義的介面卡從一個Cursor來讀取資料庫的資料,或者一耳光陣列介面卡從任意一個數組讀取資料。
風格和主題 Styles、Themes
你或許不滿意標準控制元件的外觀,你可以定製他們的風格和主題來改變他們。
@ 一個style是一個格式化的屬性集,你作為佈局的其中一個單元來使用他們。例如,你可以定義某些文字的文字大小和顏色作為特殊的view元素。
@ 一個theme主題是應用程式中整個activity的個格式化的屬性集。例如,你可以定義窗體的邊框和麵板的背景,並且設定menu的字型大小和顏色。它可以應用在整個程式裡。
風格和主題屬於資源。Android提供一些預設的風格和主題資源來讓你使用。或者你也可以自己定製他們。
宣告佈局
在一個activity裡,你的layout就是整個介面架構。它定義了顯示給使用者的元素。你可以用兩種方式宣告你的layout:
@ 在XML裡定義
android 提供了一些非常直觀的檢視類及其子類,比如一些widget和layout。
@ 在執行時新建一個例項
你的應用程式可以通過程式碼建立view或者viewGroup,並且設定它們的屬性。
Android框架給了你這兩種靈活的方法來管理和宣告你的應用程式UI。例如,你可以在xml裡宣告一個預設的佈局,包括使用者介面的元素及其屬性。你可以在執行時用過程式碼修改介面元素的包括在xml裡宣告的。
在xml裡定製UI的優點是能讓介面與邏輯部分相互獨立並且容易iguanli它們的時間。如果UI和程式碼是分離的,那意味著你可以隨時修改介面而不用修改程式碼後在編譯。例如,你可以為橫豎屏分別建立佈局,不同的介面大小不同的語言。另外,在xml宣告佈局檔案更直觀,所以你很容易找出其中的bug,所以,這篇文章會告訴你怎樣在xml裡宣告你的佈局。如果你對執行時例項化view和viewGroup感興趣,那你可以參考這兩個ViewGroup和View類。
通常,UI元素的名字和實際的功能非常接近。元素名對應著類名,屬性名對應著方法名。實際上,這種對應關係讓我們很容易的猜到xml屬性所丟應的類方法。或者才出一個類對應著哪個xml元素。然而,不是所有的命名都是相同的。有些情況下,命名會有一些不同。例如,EditText元素有一個text屬性,但卻對應著EditText.setText()方法。
小貼士:學習更多的佈局型別可以參考Common Layout Objects章節,在Hello Views裡有大量的建立佈局的例子。
編寫xml
使用Android xml的詞彙表罵你可以很快的設計出UI佈局和他們的位置。如同html那樣,有一系列的巢狀元素。
每個layout佈局檔案必須包含一個根元素,這個根元素必須是view 或者 viewGroup。一旦你定義了根元素,你可以新增它的子元素,逐漸形成一個層次的佈局。例如,下面是一個LinearLayout包含了一個TextView和Button。
[xhtml] view plain copy
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <TextView android:id="@+id/text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Hello, I am a TextView" />
- <Button android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Hello, I am a Button" />
- </LinearLayout>
在xml宣告好layout之後,儲存為以xml為字尾名的檔案,放到專案的res/layout/目錄下,然後他就會被正確的編譯。
待會我們再來討論其中的具體元素的含義。
載入xml資源
當你編譯完程式後,每個xml都程式設計一個view資源。你可以從程式碼中載入這些佈局資源,在你的activity。onCreate()方法裡。當你呼叫setContextView()之後,會把資源的引用通過R.layout_file_name的方式傳遞過去。例如你有了main_layout
.xml配置檔案,你可以在activity中這樣載入:
[java] view plain copy
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView.(R.layout.main_layout);
- }
當activity執行時,在OnCreate()回撥方法會被Android框架所呼叫。
屬性Attributes
每個View和Viewgroup物件都支援xml屬性,其中一些是特殊的,例如,textView支援textSize屬性,但這些屬性也可以繼承人和view物件來擴充套件著各類。一些屬性是公共的,因為他們繼承自根類,例如ID。其他的屬性例如layout parameters 為稱作佈局引數,這些屬性用來描述view的佈局,被他們的父view,即viewGroup定義的。
ID
每個View物件都有一個int型Id屬性,作為在檢視結構中的唯一標識。當一個程式編譯完成,id便成為一個int型的引用,但是通常在xml中的id屬性中id是一個字串。這是所有view物件所共有的基本屬性,你會經常用到。xml中的書寫語法如下:android:id="@+id/my_button"
字串開始的@符,說明xml解析器會解析@符後面剩餘的字串,並會定義他為一個id資源。“+”符號意味著必須在R.java檔案中增加這個資源。android框架會提供大量的id資源。當我們引用一個android資源id時,你不需要“+”符號,但是必須新增android包的名稱空間,像這樣:android:id="@android:id/empty"
當使用了android包的名稱空間,我們便可以使用android.r資源類了。
為了建立view 並且在程式中使用,通常的模式是:
1.在xml中定義一個viewm,並且分配一個id
[xhtml] view plain copy
- <Button android:id="@+id/my_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/my_button_text"/>
2.(通常在onCreate()方法裡)在程式碼中新建一個view物件的引用
[java] view plain copy
- Button myButton = (Button) findViewById(R.id.my_button);
在RelativeLayout相對佈局時,定義view物件的id是非常重要的,這種佈局下,兄弟view可以通過之間的位置關係來定佈局,就是通過這個唯一標識id。
在整個佈局結構中,id並不一定是唯一的,保證在當前佈局結構中唯一即可,但我們有時會使用到整個佈局,所以做好全域性唯一。
佈局引數
名為layout_something的xml屬性定義了在viewGroup裡的view的佈局引數。
每個viewGroup類實現了一個繼承自ViewGroup.LayoutParams類的巢狀類。這個子類包含了一些控制他的子View的大小位置等引數。
正如下面你所看到的,父View定義了子View的佈局:
注意每個佈局引數子類有自己的設定值的格式語法,每個子元素必須定義適合父view的佈局引數,儘管他為自己的子view也定義了不同的佈局引數。
所有的viewGroup都包含了寬高屬性,而且必須定義它們。很多佈局引數也包含了可選的間隙引數和邊界引數。
你可以用精確的值來定義寬高,儘管你並不希望經常這樣做。更多的時候,你會這樣來定義:
@ wrap_content 只佔用所需要的尺寸
@ fill_parent 佔用父viewGroup可能的最大尺寸。(在API Level 8 裡更名為 match_parent)
通常, 不建議使用畫素值來定義寬高值,我們經常用相對的單位,如與密度無關的畫素單元(dp),或者warp_content或者fill_parent來代替,這樣能確保你的程式能執行在大量不同尺寸的裝置上。公認的測量型別在 Available Respurces 文件裡被定義。
佈局位置 Layout Position
view是一個矩形,每個view都有一個位置,包含x,y起始座標和寬高來確定這個矩形的位置。位置和尺寸的單位是畫素pixel。通過呼叫getLeft()和getTop()方法可以獲得view 的位置,兩個方法返回矩形的左上角的座標xy。這些方法返回的是相對於父view的方位。比如,getLeft()返回20,那麼他的右邊距離父view左邊有20個畫素。此外,有很多方便的方法,都是為了減少不必要的計算,像getRight()和 getBottom()。(getRight()=getLeft()+getWidth())
大小、填充、邊距 Size, Padding and Margins
一個view的大小即他的寬高。一個view 實際上有兩套高度寬度值。
第一對值是我們都知道的measured width和measured 高度即測量寬度和測量高度。這組值定義了他們想在父view中有多大,通過 getMeasuredWidth() 和 getMeasuredHeight() 可以獲得他們。第二組值為width和height,或者成為 drawing width 和drawing height。這組值定義了view再被繪製到屏幕後,在螢幕中的實際大小。這些值有可能會和第一組值大小不同。通過getWidth()和getHeight()方法