第三部分:Android 應用程序接口指南---第二節:UI---第一章 用戶界面和佈局

第1章 用戶界面和佈局

應用程序的用戶界面就是用戶能看到並能夠與它交互的任何東西。Android提供多種預置的UI組件,如結構化佈局對象和容許你爲應用程序建立圖形用戶界面的UI控件。Android也會爲特殊的接口提供其餘UI模塊,如對話框,通知和菜單。在一個Android應用中,全部用戶界面元素都是由View和ViewGroup對象建立的。View 是一種能夠在屏幕上繪製某種畫面而且能夠與用戶互動的對象。ViewGroup對象則是爲了定義佈局的接口而保存其餘View(和ViewGroup)對象。Android提供一個View和ViewGroup子類的集合,這個集合能爲你提供相同的輸入控制(例如按鈕和文本框)和各類各樣的佈局模式(例如一個線性或者相對佈局)html

1.1 用戶界面佈局

對應用程序的每一個組件來講,用戶界面都是由View對象和ViewGroup對象的層次結構來定義的,如圖1-1所示。每個view group都是用來組織子view的一個不可見容器,然而子 views多是輸入控制UI或者繪製UI某些部分的其餘widgets。這個樹形結構能夠根據你的須要簡單化或複雜化。(可是對於性能來講簡單最好)java

 

圖1-1  定義UI佈局的view層次結構圖android

爲了聲明你的佈局,你能夠在代碼中實例化View對象而後啓動構建樹,但定義佈局最容易、最有效的方法是利用XML文件。XML文件能夠爲佈局提供一個可讀結構,這與HTML文件類似。一個View的XML節點名稱與它表明的Android類相對應。因此UI裏的一個<TextView>節點會建立一個TextView widget,一個<LinearLayout>節點會建立一個LinearLayout view group。例如,包含一個文本視圖和一個按鈕的簡單縱向佈局,正如代碼清單1-1所示:web

<?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="I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="I am a Button" />
</LinearLayout>

 

代碼清單1-1數據庫

當你在應用程序中載入一個佈局資源時,Android會初始化每一個進入到正運行對象的佈局節點,這時你能夠用它來定義附加行爲,查詢對象狀態,或修改佈局。數組

1.2 用戶界面組件

你不須要用View和ViewGroup對象來構建你全部的UI。Android系統提供了幾個標準UI佈局的應用程序組件,所以你只須要定義內容。這些應用程序組件都有一組惟一的API,如Action Bar,Dialogs,和Status Notifications,這些都會在他們各自的文檔中被一一介紹。異步

1.3 佈局(Layout)

佈局爲用戶界面定義了一個可視化結構。能夠用兩種方式聲明一個佈局:ide

在XML中聲明UI元素函數

Android提供了簡單的XML元素,它的元素名字與View類以及子類對應,就像佈局和widgets同樣。工具

◆在運行時動態實例化佈局元素

使用代碼建立佈局元素(而且操做他們的屬性)

 

Android提供了很是靈活的方法來聲明和管理應用UI。例如,能夠先在XML中聲明默認佈局,屏幕元素會根據它們的屬性顯示。接下來能夠在應用中添加代碼來修改屏幕對象的狀態,也能夠在運行時修改在XML中聲明的對象。 在XML中聲明UI的好處是,能夠更好地區分顯示和控制這些行爲的代碼。UI描述與應用代碼無關,也就是說能夠修改和調整XML中的UI佈局可是不用修改源java代碼。例如,可以爲不一樣的屏幕目標、不用的設備屏幕大小、不一樣的語言建立不一樣的XML佈局文件。另外,在XML中聲明佈局使得UI更容易可視化,這樣更容易調試界面。本章主要用於教會你如何在xml中聲明佈局。若是你對運行時動態建立佈局感興趣,那麼請參考viewgroup以及view類說明。 通常來講,xml聲明UI元素的詞彙和類的命名以及方法名密切相關,元素根據類名、屬性名根據方法名來命名。實際上,能猜到什麼XML屬性對應一個類的方法, 或者可以猜到哪一個類對應給定的XML元素,這每每是直接的對應。可是,注意並非全部的詞彙都是等同的。在某些狀況下,有的命名有些許不一樣。例如,EditText元素有個text屬性對應EditText.setText()方法。

1.4 寫XML

使用android的XML詞彙,能夠快速的設計UI佈局和它們包含的屏幕元素。跟建立web頁面使用html相似(一系列的嵌套)。 每個佈局文件必須包含一個根節點。這個根節點必須是一個View 或者ViewGroup對象。一旦你定義了根節點,能夠添加任意的佈局對象或者widgets做爲子元素,逐步構建一個View層次佈局。例如,這是一個XML佈局文件使用了縱向的線性佈局(LinearLayout)來排列一個TextView和Button,如代碼清單1-2所示:

<?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>

 

代碼清單1-2

這個文件應該是在當前android工程/res/layout/目錄下.xml的擴展名來保存這個文件,這樣纔會正確編譯。咱們接下來會討論這裏顯示的每一個屬性。

1.5 加載XML資源

當編譯應用程序的時候,每個XML佈局文件都被編譯到view資源中。應該在Activity.onCreate()回調方法中實現加載佈局資源。經過調用setContentView()來設置佈局資源(按照R.layout.layout_file_name的格式)。例如,若是你的XML佈局文件被保存爲main_layout.xml,那麼能夠在activity中這樣加載,如代碼清單1-3所示:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
}

 

代碼清單1-3

1.6 屬性

每個View和ViewGroup對象支持他們各自的XML屬性。有些屬性是特定的View對象(例如,TextView支持textSize屬性)可是隻要繼承這個類,這些屬性也能夠在其餘地方使用。有些屬性是對全部的的View對象都適用的,由於它們是從最原始抽象的View類繼承下來的(像id屬性)。其它的屬性被認爲是佈局參數,比較容易的理解是這樣的,ViewGroup表明佈局,View表明佈局中的元素(好比Button之類),可是ViewGroup是繼承自View的,因此你能夠理解爲,一切皆View。

1.6.1 ID

每個View對象均可能有一個int型的ID和它相關,這是在樹中View對象的惟一標識。當程序編譯完,這個ID就是一個引用,可是ID屬性在XML佈局文件裏面是經過string類型賦值的。下面讓咱們看一下XML中如何定義一個View對象的ID:

android:id="@+id/my_button"

這個@符號在字符串開頭代表xml解析器會解析和擴展剩餘的ID字符串,並把它定義爲ID資源。「+」表示這是一個新的資源名字,要建立而且增長的咱們的資源中(在R.java文件裏)。Android framework層也提供了一部分ID資源。若是直接使用android 資源ID的話,你不須要」+」,可是要加上android包名命名空間,以下所示:

android:id="@android:id/empty"

Android的包命名空間中,咱們如今引用android.R資源類的ID,而不是本地的資源類中引用。 爲了建立views,並在應用中使用,經常使用的流程以下:

1.在佈局文件中建立view/widget,併爲他們分配一個惟一的ID

<Button android:id="@+id/my_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/my_button_text"/>

 

2.接下來在代碼中建立view對象實例,從佈局中找到它(通常在OnCreate()方法中)

Button myButton = (Button) findViewById(R.id.my_button);

 

若是是在相對佈局(RelativeLayout)中的話定義好ID是很是重要的。由於它們的佈局定義就是須要依賴ID。一個ID在整個樹中不必定要求惟一,可是你搜索的部分樹應該是惟一的(常常是整個樹,因此最好的辦法是在整個樹中是惟一的)儘可能讓你的ID全局惟一。

1.6.1佈局參數

XML佈局屬性命名爲layout_something 的文件,在其所在的視圖組中定義了合適的view的佈局參數。

每個ViewGroup類都是繼承了Viewgroup.LayoutParams。通常子類使用父類的佈局參數,剛開始也許有些難理解,讓咱們看下圖1-2::

 

圖1-2 帶佈局參數的View層級

每個佈局參數子類擁有本身的語法賦值。每個子元素必須根據父元素來定義恰當的佈局參數,儘管父元素也爲它的子元素定義了不一樣的佈局參數。全部的ViewGroup包含寬度和高度,每個View都要定義這兩個屬性。許多佈局參數也包含可選邊距。寬度和高度可使用精確的測量工具,但通常不這麼作。每每,會使用這些常量來設置寬度和高度。

◆wrap_content會根據內容自動調整視圖到合適的大小(就是內容多大,寬高就多大)。

◆fill_parent會告訴你的View變成和父ViewGroup的範圍同樣大。

通常說來,不推薦使用用絕對單位像是像素來指定佈局的寬度和高度。而使用相對的測量工具像是與密度無關的單位(dp),wrap_content,或者fill_parent是一種較好的方法,由於它可以保證您的應用程序在不一樣屏幕大小的設備上都可以正常顯示。

1.7 佈局位置

一個View的幾何形狀是一個矩形。一個View有一個座標、用left和top參數,和兩個表示寬高尺寸的參數表示,你能夠理解爲一個左上角的點,和根據這個點的寬高就是一個矩形了。座標和尺寸的單位是像素。調用getLeft()和getTop()方法可以獲得視圖的座標。前者返回left、或者X軸的座標。後者返回top,或者Y軸座標。這些方法都返回的View座標是相對於父視圖的座標。好比,若是getLeft()返回20,這表示當前視圖在父視圖左側邊緣向右20個像素的地方。另外,提供了許多便利的方法避免了沒必要要的計算,像是getRight()和getBottom()這些方法返回視圖矩形的右側和底側邊緣。例如,調用getRight()和進行這個計算是同樣的:getLeft()+getWidth()。

1.8 大小,填充(padding)和邊距(Margins)

View大小是使用寬度和高度表示的。一個View實際上有兩對寬高值。第一對是測量獲得的寬度和高度。這些尺寸定義了一個View想在父類中佔多大。測量尺寸可以經過調用getMeasuredWidth()和getMeasuredHeight()獲得。第二對被簡單的成爲寬度和高度,有時成爲繪製的寬度和高度。這些尺寸定義了在繪製時和佈局後視圖在屏幕上的實際大小。它或許和測量獲得的寬度和高度不一樣。這些參數可以經過調用getWidth()和getHeight()獲得。

爲了測量尺寸,須要考慮padding。padding 表示View的左側、上側、右側和下側部分。padding可以用來偏移視圖中的內容、經過指定必定數量的像素。好比,左側padding是2,會讓視圖內容偏移視圖左邊緣2個像素。padding可以經過使用i setPadding(int,int,int,int)方法進行設置,調用getPaddingLeft(),getPaddingTop(),getPaddingRight()和getPaddingBottom()進行查詢。儘管View可以定義padding,它不提供任何margins的支持。只有view group提供了這樣的支持。

1.9 通常佈局

ViewGroup的每一個子類提供了惟一的方法來顯示View,接下來是在Android 平臺經常使用一些的佈局類型。 注意:雖然爲了UI設計,能夠在一個佈局裏面放置一個或者多個佈局,可是應該力求讓佈局層次儘量的少。這樣性能更高若是視圖層次不多會繪製的很快(一個廣度視圖層次比深度層次視圖好不少)

線性佈局:這個佈局是讓其孩子組織成一個單一的水平或垂直行。若是窗口長度超出了屏幕,它會自動建立滾動條。

相對佈局:讓你可以指定子對象之間的相對位置(孩子A在孩子B的左側)或者和父對象之間的相對位置(和父對象頂端對齊)

頁面視圖:顯示web頁面

1.10 使用適配器構建佈局

若是佈局是動態的或者非預約義的,能夠在運行時使用一個佈局子類AdapterView來填充佈局。AdapterView類的子類使用一個適配器將數據綁定到它的佈局。適配器表現爲數據源和AdapterView佈局之間的中間人-適配器檢索數據(從像是數組或者數據庫查詢這樣的數據源)並將它轉換成能夠添加到AdapterView佈局視圖中的條目。通用的適配器佈局包括:

List View:顯示滾動的列的列表

Grid View:顯示滾動的網格的行和列

1.10.1用數據填充適配器佈局

能夠填充一個AdapterView,如ListView和GridView,經過將AdapterView實例綁定到一個適配器上,這個適配器從外部數據源檢索數據併爲每一個數據條目建立一個佈局。 Android提供了許多適配器子類用來檢索各類各樣的數據併爲AdapterView構建佈局。最經常使用的通用適配器是:

1. ArrayAdapter

當數據源是數組的時候,就可使用這個適配器。默認狀況下,ArrayAdapter爲每一個數組元素建立一個佈局,經過在每一個元素調用toString()後,將數據存放在TextView裏面。

例如,若是您想將一個字符串數組顯示在ListView中,使用構造器爲每一個字符串和字符串數組指定佈局初始化一個ArrayAdapter,如代碼清單1-4所示:

ArrayAdapter adapter = new ArrayAdapter<String>(this, 
        android.R.layout.simple_list_item_1, myStringArray);

代碼清單1-4

構造器參數:

◆應用程序Context

◆一個針對字符串數組中的字符串都有一個TextView的佈局

◆字符串數組

而後只須要在ListView上調用SetAdapter(),如代碼清單2-5所示:

ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);

代碼清單2-5

爲了調整元素外觀,你能夠爲了數組中的對象重寫toString()函數。或者,爲每一個元素建立非TextView的視圖(好比,想獲取每一個數組元素的ImageView)擴展AdapterArray,重寫getView()方法返回想要的View類型。

2. SimpleCursorAdapter

當數據來源是Cursor時,則使用這個適配器。在使用SimpleCursorAdapter時,必須爲Cursor的每一行數據指定使用的佈局,也必須爲Cursor的每一欄指定要使用佈局中的哪一個控件。好比,建立一個包含用戶名稱和電話號碼的列表。首先執行Cursor數據庫的查詢,返回的是Cursor一行用戶的信息,其中有用戶的名稱和電話號碼等信息;而後建立一個字符串數組用於指定將顯示Cursor的哪一列,建立一個integer數組爲每一列指定相應的視圖來放置數據,如代碼清單1-6所示:

String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, 
                        ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};

 

代碼清單1-6

初始化SimpleCursorAdapter時,傳入的佈局參數和兩個數組對Cursor每一個結果都是適用的,代碼清單1-7所示:

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, 
        R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
ListView listView = getListView();
listView.setAdapter(adapter);

代碼清單1-7

SimpleCursorAdapter接下來爲Cursor每一行使用提供的佈局來建立View,經過將每一個fromColumns元素插入到指定的View。

 

在應用程序的生命週期中,若是適配器對應數據被改變了,應該調用notifyDataSetChanged()。這會通知相應的View數據變化了,它會自我刷新。

1.10.2處理點擊(click)事件

您能夠經過實現AdapterView.OnItemClickListener接口,來處理AdapterView每一個item的click事件。如代碼清單1-8所示:

private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
    public void onItemClick(AdapterView parent, View v, int position, long id) {
        // Do something 
    }
};
listView.setOnItemClickListener(mMessageClickedHandler); 

 

代碼清單1-8

1.11 線性佈局

線性佈局(Linear Layout)是一個ViewGroup,它全部的子視圖都在一個方向對齊,水平或者垂直。你能夠經過android:orientation 屬性來指定佈局的方向。線性佈局的全部子視圖排列都是一個靠着另外一個,所以垂直列表每行僅僅有一個子視圖,無論有多寬。水平列表只能有一行的高度(最高子視圖的高度加上邊距距離)。線性佈局對於每個子視圖涉及到邊緣在子視圖和權重(左邊或者右邊以及中間對齊)之間。

 

1.11.1佈局權重(Weight)

線性佈局支持給個別的子視圖設定權重,經過android:layout_weight屬性。就一個視圖在屏幕上佔多大的空間而言,這個屬性給其設定了一個重要的值。一個大的權重值,容許它擴大到填充父視圖中的任何剩餘空間。子視圖能夠指定一個權重值,而後視圖組剩餘的其餘的空間將會分配給其聲明權重的子視圖。默認的權重是0。例如,若是有三個文本框,其中兩個聲明的權重爲1,另一個沒有權重,沒有權重第三個文本字段不會增長,只會佔用其內容所需的面積。其餘兩個一樣的會擴大以填補剩餘的空間,在三個文本域被測量後。若是第三個字段,而後給定的權重爲2(而不是0),那麼它如今的聲明比其餘的更重要,因此它獲得一半2/(2+1+1)的總的剩餘空間,而前兩個平均分配剩餘的。

若在線性佈局中建立佔有相同空間的子視圖,設置每一個子視圖的android:layout_height屬性值爲"0dp"(對於垂直線性佈局來講),或者設置每一個子視圖的android:layout_width屬性值爲"0dp"(對於水平線性佈局來講)。而後在設置每一個子視圖的android:layout_weight屬性值爲"1"。若是想更詳細的瞭解線性佈局的每一個子視圖的可用屬性,能夠參考LinearLayout.LayoutParams

下面讓咱們來看下代碼清單1-9的實例:

<?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:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:orientation="vertical" >
    <EditText
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="@string/to" />
    <EditText
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="@string/subject" />
    <EditText
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="top"
        android:hint="@string/message" />
    <Button
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:text="@string/send" />
</LinearLayout>

 

代碼清單1-9

例子運行的結果以下圖1-3所示:

 


圖1-3  運行後的效果圖

1.12 相對佈局

RelativeLayout顧名思義,相對佈局,在這個容器內部的子元素們可使用彼此之間的相對位置(例如,在某個視圖左邊left-of)或者和容器間的相對位置(例如,與父視圖左對齊,底部對齊或者居中等)來進行定位。

RelativeLayout(相對佈局)是一個爲用戶界面設計,很是強大的工具.由於它能夠消除嵌套視圖組,並保持你的佈局層次更簡潔,從而提升性能。若是你發現本身使用多個嵌套的LinearLayout組,您可能可以取代單一RelativeLayout。

1.12.1定位View

相對佈局可讓它的子View指定本身的相對於父View的位置或者視圖元素之間的相對位置(經過指定的ID)。你可使兩個元素右邊界對齊,或者使一個View在另外一個View下方, 或者使View在屏幕居中偏左等等。默認狀況下,全部的子View在佈局的左上角。因此你必須經過使用佈局屬性RelativeLayout.LayoutParams中各類不一樣的可用屬性值來定義每一個View的位置。

相對佈局View的一些可用屬性包括:

◆android:layout_alignParentTop

若是設置爲「true」,使這一View的頂部邊緣匹配父類的頂部邊緣

◆android:layout_centerVertical

若是「true」,設置此子視圖在父View中垂直居中。

◆android:layout_below

設置此視圖的上邊緣位於經過資源ID指定的View的下方。

◆android:layout_toRightOf

設置此視圖的左邊緣位於經過資源ID指定的View的右方。


這僅僅是幾個例子,全部的佈局屬性咱們能夠在RelativeLayout.LayoutParams中找到。

每一個佈局屬性的值既能夠是boolean類型的值來肯定佈局相對於父佈局的位置,也能夠是某個子View的ID,來指定佈局相對於這個子View的位置。

在你的xml佈局文件中,依賴於其餘視圖的佈局能夠在聲明的時候沒有順序。例如:

你能夠聲明「View1」在「VIew2」的下方,即便View2是在視圖層次結構中最後一個被聲明的。下面的例子演示了這種狀況。(這是官方的說法,但筆者遇到過的實際狀況是順序是有影響的),下面讓咱們看下代碼清單1-10:

<?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"
    android:paddingLeft="16dp"
    android:paddingRight="16dp" >
    <EditText
        android:id="@+id/name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="@string/reminder" />
    <Spinner
        android:id="@+id/dates"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/name"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@+id/times" />
    <Spinner
        android:id="@id/times"
        android:layout_width="96dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/name"
        android:layout_alignParentRight="true" />
    <Button
        android:layout_width="96dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/times"
        android:layout_alignParentRight="true"
        android:text="@string/done" />
</RelativeLayout>

 

代碼清單1-10

例子運行的結果以下圖1-4所示:

 

 

圖1-4  運行後的效果圖

1.13 List View

列表視圖是一個縱向顯示滾動項的View組合。每一列的項都經過Adapter被自動插入到列表中,其中,Adapter適配器能夠從數組或者數據庫查詢中提取出內容並轉化成列表View中的item。

 

1.13.1使用一個裝載器

使用一個CursorLoade是避免一個異步任務查詢光標Curso時阻塞程序主線程的標準途徑。當CursorLoader收到一個Cursor結果,LoaderCallbacks會收到一個對onLoadFinished()的回調,這時能夠利用新的Cursor和列表視圖更新Adapter並顯示結果。

雖然CursorLoader函數在Android3.0(API級別 11)中才第一次引入,程序能夠經過引入Support Library使用它們來支持運行Android 1.6及以上的設備。

要查看更多關於利用Loader異步加載數據的信息,請參看Loaders

下面的例子是把ListView做爲惟一默認佈局元素的活動ListActivity。它完成向Contacts Provider查詢姓名和電話號碼清單的功能。

爲了使用CursorLoader向列表動態加載數據,這個活動實現了LoaderCallbacks接口。如代碼清單1-11所示:

public class ListViewLoader extends ListActivity
        implements LoaderManager.LoaderCallbacks<Cursor> {
 
      SimpleCursorAdapter mAdapter;
 
 
    static final String[] PROJECTION = new String[] {ContactsContract.Data._ID,
            ContactsContract.Data.DISPLAY_NAME};
 
    static final String SELECTION = "((" + 
            ContactsContract.Data.DISPLAY_NAME + " NOTNULL) AND (" +
            ContactsContract.Data.DISPLAY_NAME + " != '' ))";
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        ProgressBar progressBar = new ProgressBar(this);
        progressBar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT, Gravity.CENTER));
        progressBar.setIndeterminate(true);
        getListView().setEmptyView(progressBar);
 
              ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
        root.addView(progressBar);
 
        
        String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};
        int[] toViews = {android.R.id.text1}; 
     
        mAdapter = new SimpleCursorAdapter(this, 
                android.R.layout.simple_list_item_1, null,
                fromColumns, toViews, 0);
        setListAdapter(mAdapter);
 
      
        getLoaderManager().initLoader(0, null, this);
    }
 
      public Loader<Cursor> onCreateLoader(int id, Bundle args) {
      
        return new CursorLoader(this, ContactsContract.Data.CONTENT_URI,
                PROJECTION, SELECTION, null, null);
    }
 
      public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
     
        mAdapter.swapCursor(data);
    }
 
        public void onLoaderReset(Loader<Cursor> loader) {
    
        mAdapter.swapCursor(null);
    }
 
    @Override 
    public void onListItemClick(ListView l, View v, int position, long id) {
    }
}

 

代碼清單1-11

注意:由於這個例子要向Contacts Provider請求查詢數據,程序須要在製做清單文件中請求READ_CONTACTS權限:

<uses-permission android:name="android.permission.READ_CONTACTS" />

 

1.14 Grid View

GridView是一個在可滾動的二維網格空間中顯示item的ViewGroup。元件會使用ListAdapter自動插入網格佈局中。

 

在本教程中,將建立一個縮略圖網格。當一個item被選中,會彈出顯示該圖像的位置的消息框。

1. 首先建立一個名爲HelloGridView的工程

2. 找出一些將要使用的的圖像。將準備好的圖像放在工程的res/drawable/目錄下。

3. 打開 res/layout/main.xml文件,並插入如下代碼清單1-12:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/gridview"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"
    android:columnWidth="90dp"
    android:numColumns="auto_fit"
    android:verticalSpacing="10dp"
    android:horizontalSpacing="10dp"
    android:stretchMode="columnWidth"
    android:gravity="center"
/>

 

代碼清單1-12

建立的GridView將填滿整個屏幕。這些屬性的含義都很明顯。更多關於屬性的信息,請參閱的GridView的參考。

四、打開 HelloGridView.java 並在其中的onCreate()函數中插入如下代碼清單1-13:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
 
    GridView gridview = (GridView) findViewById(R.id.gridview);
    gridview.setAdapter(new ImageAdapter(this));
 
    gridview.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
            Toast.makeText(HelloGridView.this, "" + position, Toast.LENGTH_SHORT).show();
        }
    });
}

 

代碼清單1-13

當main.xml文件完成內容佈局之後,GridView會被findViewById(int)方法從佈局中捕捉到。setAdapter()方法設置一個自定義的適配器(ImageAdapter)做爲被顯示在網格中的元件的源。ImageAdapter會在下一步中建立。

setOnItemClickListener()會傳遞一個新的 AdapterView.OnItemClickListener消息以便於響應網格元件被選中的事件。 匿名實例定義了由onItemClick()回調函數彈出一個Toast消息框顯示所選中的網格元件的位置索引號(索引號從零開始計算。在實際程序中能夠經過位置索引號獲取其全尺寸圖像以備其餘用途)。

5. 建立一個擴展BaseAdapter並調用ImageAdapter的新類,如代碼清代1-14:

public class ImageAdapter extends BaseAdapter {
    private Context mContext;
 
    public ImageAdapter(Context c) {
        mContext = c;
    }
 
    public int getCount() {
        return mThumbIds.length;
    }
 
    public Object getItem(int position) {
        return null;
    }
 
    public long getItemId(int position) {
        return 0;
    }
 
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) { 
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8, 8, 8, 8);
        } else {
            imageView = (ImageView) convertView;
        }
 
        imageView.setImageResource(mThumbIds[position]);
        return imageView;
    }
 
      private Integer[] mThumbIds = {
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7,
            R.drawable.sample_0, R.drawable.sample_1,
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7,
            R.drawable.sample_0, R.drawable.sample_1,
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7
    };
}

 

代碼清單1-14

首先,實例化一些繼承自BaseAdapter的必要函數。構造函數和getCount()不用多解釋。一般狀況下,getItem(int)應該返回一個適配器中指定位置的真實對象,可是在本例中這點被忽略了。一樣的,getItemId(int)應該返回元件的真實編號,可是本例中不須要這樣。

第一個必須的方法是getView()。這個方法爲每個加入到ImageAdapter的圖像建立一個新的View視圖。當調用它時,一個View視圖對象會被傳入而且是可重複使用的(在被調用至少一次之後),因此須要確認對象是否爲空。若是爲空,就要實例化一個ImageView並根據要呈現的圖像設置屬性參數。

setLayoutParams(ViewGroup.LayoutParams)設置視圖的高度和寬度,這樣能夠確保不論原圖像的大小如何都能適當的調整大小和裁減。

setScaleType(ImageView.ScaleType)聲明瞭圖像將依照中心進行裁減(若是須要的話)。

int, int, int) setPadding(int, int, int, int)定義了各邊如何進行填充。(須要注意的是,若是圖像有不一樣的縱橫比,那麼當圖像不匹配ImageView給定的尺寸時,較少的填充就會致使圖像更多的裁減)。

若是傳給android.view.View, android.view.ViewGroup) getView()的View視圖不爲空,則本地的ImageView會由可重複使用的View初始化。

在getView()方法的最後,被傳入的position參數會用於從被做爲ImageView資源的mThumbIds數組中選擇圖像。

剩下的就是定義繪畫資源的mThumbIds數組。

6. 運行程序。

能夠經過調整GridVie和ImageView的元素體驗其使用方法。例如,使用setAdjustViewBounds(boolean)而不使用setLayoutParams(ViewGroup.LayoutParams)。

  本文來自jy02432443,是本人辛辛苦苦一個個字碼出來的,轉載請保留出處,並保留追究法律責任的權利 QQ78117253 

相關文章
相關標籤/搜索