佈局定義用戶界面的視覺結構,如Activity或應用小部件的 UI。您能夠經過兩種方式聲明佈局:java
在 XML 中聲明 UI 元素。Android 提供了對應於 View 類及其子類的簡明 XML 詞彙,如用於小部件和佈局的詞彙;
運行時實例化佈局元素。您的應用能夠經過編程建立 View 對象和 ViewGroup 對象(並操縱其屬性)。
Android 框架讓您能夠靈活地使用如下一種或兩種方法來聲明和管理應用的 UI。例如,您能夠在 XML 中聲明應用的默認佈局,包括將出如今佈局中的屏幕元素及其屬性。而後,您能夠在應用中添加可在運行時修改屏幕對象(包括那些已在 XML 中聲明的對象)狀態的代碼。android
您還應嘗試使用層次結構查看器工具來調試佈局—當您在模擬器或設備上進行調試時,它會顯示佈局屬性值、繪製具備內邊距/外邊距指示符的線框以及完整渲染視圖。
您能夠利用 layoutopt 工具快速分析佈局和層次結構中是否存在低效環節或其餘問題。
在 XML 中聲明 UI 的優勢在於,您能夠更好地將應用的外觀與控制應用行爲的代碼隔離。您的 UI 描述位於應用代碼外部,這意味着您在修改或調整描述時無需修改您的源代碼並從新編譯。例如,您能夠建立適用於不一樣屏幕方向、不一樣設備屏幕尺寸和不一樣語言的 XML 佈局。此外,在 XML 中聲明佈局還能更輕鬆地顯示 UI 的結構,從而簡化問題調試過程。所以,本文將側重於示範如何在 XML 中聲明佈局。若是您對在運行時實例化 View 對象感興趣,請參閱 ViewGroup 類和 View 類的參考資料。數據庫
通常而言,用於聲明 UI 元素的 XML 詞彙嚴格遵循類和方法的結構和命名方式,其中元素名稱對應於類名稱,屬性名稱對應於方法。實際上,這種對應關係每每很是直接,讓您能夠猜到對應於類方法的 XML 屬性,或對應於給定 XML 元素的類。但請注意,並不是全部詞彙都徹底相同。在某些狀況下,在命名上略有差別。例如,EditText 元素具備的 text 屬性對應的類方法是 EditText.setText()。編程
提示:如需瞭解有關不一樣佈局類型的更多信息,請參閱常見佈局對象。數組
您能夠利用 Android 的 XML 詞彙,按照在 HTML 中建立包含一系列嵌套元素的網頁的相同方式快速設計 UI 佈局及其包含的屏幕元素。bash
每一個佈局文件都必須只包含一個根元素,而且該元素必須是視圖對象或 ViewGroup 對象。定義根元素以後,便可再以子元素的形式添加其餘佈局對象或小部件,從而逐步構建定義佈局的視圖層次結構。例如,如下這個 XML 佈局使用垂直 LinearLayout 來儲存一個 TextView 和一個 Button:框架
<?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" >
<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 中聲明佈局後,請在您的 Android 項目 res/layout/ 目錄中以 .xml 擴展名保存文件,以便其可以正確編譯。函數
佈局資源文檔中提供了有關佈局 XML 文件語法的更多信息。工具
當您編譯應用時,每一個 XML 佈局文件都會編譯到一個 View 資源中。 您應該在 Activity.onCreate() 回調實現中從您的應用代碼加載佈局資源。請經過調用 setContentView(),以 R.layout.layout_file_name 形式向其傳遞對佈局資源的引用來執行此操做。例如,若是您的 XML 佈局保存爲 main_layout.xml,則須要像下面這樣爲您的 Activity 加載該佈局:佈局
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
}複製代碼
啓動您的 Activity 時,Android 框架會調用 Activity 中的 onCreate() 回調方法(請參閱Activity文檔中有關生命週期的闡述)。
每一個視圖對象和 ViewGroup 對象都支持各自的各種 XML 屬性。某些屬性是視圖對象的專用屬性(例如,TextView 支持 textSize 屬性),但這些屬性也會被任何能夠擴展此類的視圖對象繼承。某些屬性通用於全部 View 對象,由於它們繼承自根 View 類(如 id 屬性)。此外,其餘屬性被視爲「佈局參數」,即描述 View 對象特定佈局方向的屬性,如該對象的父 ViewGroup 對象所定義的屬性。
任何視圖對象均可能具備關聯的整型 ID,此 ID 用於在結構樹中對 View 對象進行惟一標識。編譯應用後,此 ID 將做爲整型數引用,但在佈局 XML 文件中,一般會在 id 屬性中爲該 ID 賦予字符串值。這是全部 View 對象共用的 XML 屬性(由 View 類定義),您會常常用到它。XML 標記內部的 ID 語法是:
android:id="@+id/my_button"
字符串開頭處的 @ 符號指示 XML 解析程序應該解析並展開 ID 字符串的其他部分,並將其標識爲 ID 資源。加號 (+) 表示這是一個新的資源名稱,必須建立該名稱並將其添加到咱們的資源(在 R.java 文件中)內。Android 框架還提供了許多其餘 ID 資源。 引用 Android 資源 ID 時,不須要加號,但必須添加 android 軟件包命名空間,以下所示:
android:id="@android:id/empty"
添加 android 軟件包命名空間以後,如今,咱們將從 android.R 資源類而非本地資源類引用 ID。
要想建立視圖並從應用中引用它們,常見的模式是:
在佈局文件中定義一個視圖/小部件,併爲其分配一個惟一的 ID:
<Button android:id="@+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/my_button_text"/>複製代碼
而後建立一個 view 對象實例,並從佈局中捕獲它(一般使用 onCreate() 方法):
Button myButton = (Button) findViewById(R.id.my_button);
建立 RelativeLayout 時,爲 view 對象定義 ID 很是重要。在相對佈局中,同級視圖能夠定義其相對於其餘同級視圖的佈局,同級視圖經過惟一的 ID 進行引用。
ID 不須要在整個結構樹中具備惟一性,但在您要搜索的結構樹部分應具備惟一性(要搜索的部分每每是整個結構樹,所以最好儘量具備全局惟一性)。
名爲 layout_something 的 XML 佈局屬性可爲視圖定義與其所在的 ViewGroup 相適的佈局參數。
每一個 ViewGroup 類都會實現一個擴展 ViewGroup.LayoutParams 的嵌套類。此子類包含的屬性類型會根據須要爲視圖組的每一個子視圖定義尺寸和位置。 正如您在圖 1 中所見,父視圖組爲每一個子視圖(包括子視圖組)定義佈局參數。
圖 以可視化方式表示的視圖層次結構,其中包含與每一個視圖關聯的佈局參數。
請注意,每一個 LayoutParams 子類都有本身的值設置語法。 每一個子元素都必須定義適合其父元素的 LayoutParams,但父元素也可爲其子元素定義不一樣的 LayoutParams。
全部視圖組都包括寬度和高度(layout_width 和 layout_height),而且每一個視圖都必須定義它們。許多 LayoutParams 還包括可選的外邊距和邊框。
您能夠指定具備確切尺寸的寬度和高度,但您多半不想常常這樣作。 在更多的狀況下,您會使用如下常量之一來設置寬度或高度:
wrap_content 指示您的視圖將其大小調整爲內容所需的尺寸。
match_parent 指示您的視圖儘量採用其父視圖組所容許的最大尺寸。
通常而言,建議不要使用絕對單位(如像素)來指定佈局寬度和高度, 而是使用相對測量單位,如密度無關像素單位 (dp)、wrap_content 或 match_parent,這種方法更好,由於它有助於確保您的應用在各種尺寸的設備屏幕上正確顯示。可用資源文檔中定義了可接受的測量單位類型。
視圖的幾何形狀就是矩形的幾何形狀。視圖具備一個位置(以一對水平向左和垂直向上座標表示)和兩個尺寸(以寬度和高度表示)。 位置和尺寸的單位是像素。
能夠經過調用方法 getLeft() 和方法 getTop() 來檢索視圖的位置。前者會返回表示視圖的矩形的水平向左(或稱 X 軸) 座標。後者會返回表示視圖的矩形的垂直向上(或稱 Y 軸)座標。 這些方法都會返回視圖相對於其父項的位置。 例如,若是 getLeft() 返回 20,則意味着視圖位於其直接父項左邊緣向右 20 個像素處。
此外,系統還提供了幾種便捷方法來避免沒必要要的計算,即 getRight() 和 getBottom()。 這些方法會返回表示視圖的矩形的右邊緣和下邊緣的座標。 例如,調用 getRight() 相似於進行如下計算:getLeft() + getWidth()。
視圖的尺寸經過寬度和高度表示。視圖實際上具備兩對寬度和高度值。
第一對稱爲測量寬度和測量高度。 這些尺寸定義視圖想要在其父項內具備的大小。 這些測量尺寸能夠經過調用 getMeasuredWidth() 和 getMeasuredHeight() 來得到。
第二對簡稱爲寬度和高度,有時稱爲繪製寬度和繪製高度。 這些尺寸定義視圖在繪製時和佈局後在屏幕上的實際尺寸。 這些值能夠(但沒必要)與測量寬度和測量高度不一樣。 寬度和高度能夠經過調用 getWidth() 和 getHeight() 來得到。
要想測量其尺寸,視圖須要將其內邊距考慮在內。內邊距以視圖左側、頂部、右側和底部各部分的像素數表示。 內邊距可用於以特定數量的像素彌補視圖的內容。 例如,左側內邊距爲 2,會將視圖的內容從左邊緣向右推 2 個像素。 可使用 setPadding(int, int, int, int) 方法設置內邊距,並經過調用 getPaddingLeft()、getPaddingTop()、getPaddingRight() 和 getPaddingBottom() 進行查詢。
儘管視圖能夠定義內邊距,但它並不支持外邊距。 不過,視圖組能夠提供此類支持。如需瞭解更多信息,請參閱 ViewGroup 和 ViewGroup.MarginLayoutParams。
ViewGroup 類的每一個子類都提供了一種獨特的方式來顯示您在其中嵌套的視圖。如下是 Android 平臺中內置的一些較爲常見的佈局類型。
注:儘管您能夠經過將一個或多個佈局嵌套在另外一個佈局內來實現您的 UI 設計,但應該使您的佈局層次結構儘量簡略。佈局的嵌套佈局越少,繪製速度越快(扁平的視圖層次結構優於深層的視圖層次結構)。
一種使用單個水平行或垂直行來組織子項的佈局。它會在窗口長度超出屏幕長度時建立一個滾動條。
讓您可以指定子對象彼此之間的相對位置(子對象 A 在子對象 B 左側)或子對象與父對象的相對位置(與父對象頂部對齊)。
顯示網頁。
使用適配器構建佈局
若是佈局的內容是屬於動態或未預先肯定的內容,您可使用這樣一種佈局:在運行時經過子類 AdapterView 用視圖填充佈局。 AdapterView 類的子類使用 Adapter 將數據與其佈局綁定。Adapter 充當數據源與 AdapterView 佈局之間的中間人—Adapter(從數組或數據庫查詢等來源)檢索數據,並將每一個條目轉換爲能夠添加到 AdapterView 佈局中的視圖。
列表視圖
顯示滾動的單列列表。
網格視圖
顯示滾動的行列網格。
使用數據填充適配器視圖
您能夠經過將 AdapterView 實例與 Adapter 綁定來填充 AdapterView(如 ListView 或 GridView),此操做會從外部來源檢索數據,並建立表示每一個數據條目的 View。
Android 提供了幾個 Adapter 子類,用於檢索不一樣種類的數據和構建 AdapterView 的視圖。 兩種最多見的適配器是:
請在數據源爲數組時使用此適配器。默認狀況下,ArrayAdapter 會經過在每一個項目上調用 toString() 並將內容放入 TextView 來爲每一個數組項建立視圖。
例如,若是您具備想要在 ListView 中顯示的字符串數組,請使用構造函數初始化一個新的 ArrayAdapter,爲每一個字符串和字符串數組指定佈局:
ArrayAdapter adapter = new ArrayAdapter(this,
android.R.layout.simple_list_item_1, myStringArray);
此構造函數的參數是:
您的應用 Context
包含數組中每一個字符串的 TextView 的佈局
字符串數組
而後,只需在您的 ListView 上調用 setAdapter():
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
要想自定義每一個項的外觀,您能夠重寫數組中各個對象的 toString() 方法。或者,要想爲 TextView 以外的每一個項建立視圖(例如,若是您想爲每一個數組項建立一個 ImageView),請擴展 ArrayAdapter 類並重寫 getView() 以返回您想要爲每一個項獲取的視圖類型。
請在數據來自 Cursor 時使用此適配器。使用 SimpleCursorAdapter 時,您必須指定要爲 Cursor 中的每一個行使用的佈局,以及應該在哪些佈局視圖中插入 Cursor 中的哪些列。 例如,若是您想建立人員姓名和電話號碼列表,則能夠執行一個返回 Cursor(包含對應每一個人的行,以及對應姓名和號碼的列)的查詢。 而後,您能夠建立一個字符串數組,指定您想要在每一個結果的佈局中包含 Cursor 中的哪些列,並建立一個整型數組,指定應該將每一個列放入的對應視圖:
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};
當您實例化 SimpleCursorAdapter 時,請傳遞要用於每一個結果的佈局、包含結果的 Cursor 以及如下兩個數組:
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
ListView listView = getListView();
listView.setAdapter(adapter);
而後,SimpleCursorAdapter 會使用提供的佈局,將每一個 fromColumns 項插入對應的 toViews 視圖,爲 Cursor 中的每一個行建立一個視圖。
若是您在應用的生命週期中更改了適配器讀取的底層數據,則應調用 notifyDataSetChanged()。此操做會通知附加的視圖,數據發生了變化,它應該自行刷新。
您能夠經過實現 AdapterView.OnItemClickListener 界面來響應 AdapterView 中每一項上的點擊事件。 例如:
// Create a message handling object as an anonymous class.
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
// Do something in response to the click
}
};
listView.setOnItemClickListener(mMessageClickedHandler);
個人文章首發於公衆號
互聯網學術(IT-paper)
掃碼上車瞭解最新互聯網學術熱點複製代碼