第2章 輸入控件
輸入控件是應用程序中用戶接口的一種交互式組件。Android提供了大量的可供人們在UI中使用的控件,比如按鈕、文本區域、(帶滑塊的)進度條、復選框、縮放按鈕以及切換按鈕等等。
在UI中增加輸入控件就如同在XML布局中增加XNL元素一樣簡單。舉例來說,下面為一個帶有文本區域和按鈕的布局。先看下圖2-1的效果:
圖2-1 各種輸入控件
接下來然我們看下代碼清單2-1是如何布局上面這些控件的:
<?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="horizontal"> <EditText android:id="@+id/edit_message" android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:hint="@string/edit_message" /> <Button android:id="@+id/button_send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_send" android:onClick="sendMessage" /> </LinearLayout>
代碼清單2-1
每個輸入控件都支持一個特定的輸入事件,如當用戶輸入文本或觸摸一個按鈕,這樣你就可以處理事件。
2.1 常用控件
下面是一些常見的控件的清單,您可以在您的應用程序中使用它們。點擊下面的鏈接,以了解每個控件更多的使用。注意:Android提供了比這里列出來的更多的控件,可以通過瀏覽android.widget包發現更多的控件。如果您的應用程序需要特定的輸入控件,你可以建立自己的自定義組件。下面讓我們來看一下表格2-1:
控件類型 |
描述 |
相關類 |
按鈕 |
一個按鈕,可以被用戶按下或點擊,以執行一個動作。 |
Button |
文本域 |
一個可編輯的文本區域。你可以使用AutoCompleteTextView小部件來創建一個文本輸入部件,以提供自動完成建議 |
EditText,AutoCompleteTextView |
復選框 |
一個可以由用戶切換的ON/OFF開關。當提供給用戶一組不互斥的可選項時,你應該使用復選框。 |
CheckBox |
單選按鈕 |
與復選框類似,但一組里只可以選擇一個選項。 |
RadioGroup |
開關按鈕 |
帶有亮度指示的ON/OFF的按鈕 |
ToggleButton |
下拉列表 |
一個下拉列表,允許用戶從一組數據中選擇一個值。 |
Spinner |
選擇器 |
一個對話框供用戶通過使用向上/向下按鈕或手勢從一系列值中選擇一個值。使用DatePicker部件來輸入日期(月,日,年)或使用TimePicker部件輸入時間(小時,分鍾,上午/下午),這將被自動的格式化為用戶區域的值。 |
DatePicker,TimePicker |
表格2-1
2.2 按鈕(Buttons)
按鈕包括文字或者圖標,或者兩者兼而有之,當用戶觸摸到按鈕時就會觸發事件。如圖2-2所示:
圖2-2 各種按鈕
取決於你需要按鈕有文本、圖標或兩者兼而有之,您可以以三種方式創建按鈕布局:
需要有文字的按鈕,使用Button類,如代碼清單2-2所示:
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_text" ... />
代碼清單2-2
需要有圖標的按鈕,使用ImageButton類,如代碼清單2-3所示:
<ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/button_icon" ... />
代碼清單2-3
需要有文字和圖標的按鈕,使用具有android:drawableLeft屬性的Button類,如代碼清單2-4所示:
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_text" android:drawableLeft="@drawable/button_icon" ... />
代碼清單2-4
2.2.1響應點擊事件
當用戶點擊一個按鈕時,Button對象就會收到一個單擊事件。
為了定義一個按鈕的點擊事件處理程序,你可以在XML布局中<button元素添加android:onClick屬性。這個屬性的值必須是你要調用的方法響應點擊事件的名稱。 使用這個布局的Activity必須執行相應的方法。例如,這里有一個使用android:onClick屬性的按鈕的布局,如代碼清單2-5所示:
<?xml version="1.0" encoding="utf-8"?> <Button xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/button_send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_send" android:onClick="sendMessage" />
代碼清單2-5
在使用這個布局的Activity中,利用下面的方法處理點擊事件,代碼清單2-6所示:
public void sendMessage(View view) { }
代碼清單2-6
在android:onClick屬性聲明的方法必須完全按照上面顯示。具體來說,該方法必須:
◆是public
◆返回void
◆定義一個View作為其唯一的參數
當然除了在xml中定義以外,你可以使用監聽器(OnClickListener)
您也可以聲明單擊事件處理程序,而不是在XML布局中。因為某些情況下,如果你在運行時實例化Button,或者你需要在一個Fragment子類中聲明單擊事件。就需要使用setOnClickListener例如,代碼清單2-7所示:
Button button = (Button) findViewById(R.id.button_send); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Do something } });
代碼清單2-7
2.2.2按鈕的樣式風格(Styling)
按鈕的外觀(背景圖片和字體)可能會因為機器不同而有所不同,因為不同廠家的設備的輸入控件的默認樣式往往不同。您可以控制控件使用適用於整個應用程序的樣式。例如,要確保所有運行Android4.0甚至更高版本的設備在您的應用程序使用Holo主題,需要在manifest的 <application>元素中聲明android:theme="@android:style/Theme.Holo"。為了給按鈕定制不同的背景,指定android:background屬性為圖片或顏色。另外,您可以使用一種類似於HTML的樣式來定義按鈕的樣式,可以定義多種屬性,如背景、字體、大小等等。
1. 無邊框按鈕
一種有用的設計是無邊框按鈕。無邊框按鈕與基本按鈕相似,但是無邊框按鈕沒有無邊框或背景,但在不同狀態如點擊時,會改變外觀。要創建一個無邊框按鈕,需要為按鈕應用borderlessButtonStyle樣式。如代碼清單2-8所示:
<Button android:id="@+id/button_send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_send" android:onClick="sendMessage" style="?android:attr/borderlessButtonStyle" />
代碼清單2-8
2. 自定義背景
如果你想真正重新定義按鈕的外觀,你可以指定一個自定義的背景。而不是提供一個簡單的位圖或顏色,你的背景應該是一個狀態列表資源,取決於按鈕的當前狀態而改變外觀,。
您可以在一個XML文件中定義狀態列表,定義三種不同的圖像或顏色,用於不同的按鈕狀態。
要為按鈕的背景創建一個狀態列表資源,需要以下步驟:
◆創建三個按鈕背景位圖以表示默認、按下和選中的按鈕狀態。
為了確保圖像適合不同大小的按鈕,以<9-patch>的格式創建圖像。
◆位圖放到你工程的res/drawable/ directory。確保每個位圖命名正確能夠反映它們分別代表的按鈕狀態,如button_default.9.png、button_pressed.9.png以及button_focused.9.png。
◆在res/drawable/ directory下創建一個新的XML文件(命名如button_custom.xml)。使用下面的XML,如代碼清單2-9所示:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/button_pressed" android:state_pressed="true" /> <item android:drawable="@drawable/button_focused" android:state_focused="true" /> <item android:drawable="@drawable/button_default" /> </selector>
代碼清單2-9
這定義一個單一的繪制資源,將基於按鈕的當前狀態改變其圖像。
第一個<item>定義了按下按鈕(激活)時使用的位圖。
第二個<item>定義了按鈕按下時(按鈕高亮時,使用軌跡球或方向鍵)使用的位圖。
第三個<item>定義了默認狀態下的按鈕(既不是按下也不是選中)使用的位圖。
注意:<item>元素的順序是重要的。當圖像可用時,按順序遍歷<item>元素,以確定哪一個適合當前按鈕狀態。因為默認的位圖在最后,當android:state_pressed 和android:state_focused的值都為false時才會被應用。
現在這個XML文件代表一個單一的繪制資源,當<Button>引用它作為背景,圖像將基於按鈕的三種狀態而改變。
◆最后,只需應用此XML文件作為按鈕的背景,如代碼清單2-10所示:
<Button android:id="@+id/button_send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_send" android:onClick="sendMessage" android:background="@drawable/button_custom" />
代碼清單2-10
2.3 文本域(Text Fields)
文本域允許用戶在應用程序中輸入文本。它們可以是單行的,也可以是多行的。點擊文本域后顯示光標,並自動顯示鍵盤。除了輸入,文本域還包含其它操作,比如文本選擇(剪切,復制,粘貼)以及數據的自動查找功能。你可以使用EditText對象在布局中添加一個文本字段, android里的寫法通常是在XML布局文件中添加<EditText>元素,點擊后的效果如圖2-3所示:
圖2-3 點擊文本域后彈出的界面
2.3.1指定鍵盤類型
文本字段可以有不同的輸入類型,如數字,日期,密碼,或電子郵件地址。類型確定文本框內允許輸入什么樣的字符,可能會提示虛擬鍵盤調整其布局來顯示最常用的字符。你可以在EditText對象使用Android:inputType屬性指定輸入類型的鍵盤,例如:你想輸入一個電子郵件地址上的用戶,inputType屬性應為textEmailAddress。如代碼清單2-11所示:
<EditText android:id="@+id/email_address" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/email_hint" android:inputType="textEmailAddress" />
代碼清單2-11
針對不同的情況有幾種不同的輸入類型。你可以找到所有的文件中列出的android:inputType屬性,下面讓我們看下各種圖:
圖2-4 默認的文本輸入類型
圖2-5 textEmailAddress文本輸入類型
提示:為了讓用戶輸入長文本字符串時換行,使用的“textMultiLine”屬性。默認情況下,一個編輯文本對象僅限於一行文本和水平滾動文本時超過可用寬度。
圖2-6 phone文本輸入類型
android:inputType還允許您指定操作行為,如在某此鍵盤上是否要利用所有新詞,或使用自動完成和拼寫建議功能。在android:inputType的屬性允許組合,讓您可以一次指定一個鍵盤布局和一個或多個操作行為。例如,你如何收集郵政地址,利用每一個字,並禁用文字的行為,如代碼清單2-12所示:
<EditText android:id="@+id/postal_address" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/postal_address_hint" android:inputType="textPostalAddress| textCapWords| textNoSuggestions" />
代碼清單2-12
2.3.1指定鍵盤操作
除了改變鍵盤的輸入類型,當用戶完成輸入時,android允許你指定特殊的按鈕進行相應的操作,如把回車鍵作為 “搜索”或 “發送”操作。
圖2-7 如果你聲明的Android imeOptions =“actionSend” ,鍵盤包括發送的動作。
您可以通過android:imeOptions屬性設置指定的動作。例如,這里你可以指定發送的行為,如代碼清單2-13所示:
<EditText android:id="@+id/search" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/search_hint" android:inputType="text" android:imeOptions="actionSend" />
代碼清單2-13
如果你不明確指定一個輸入動作,然后系統將嘗試確定是否有任何后續的android:focusable屬性動作。如果發現了有android:focusable屬性動作,那么這個系統適用於在當前的EditText的 actionNext行動,使用戶可以選擇“下一步”或移動到下一個字段。如果是沒有后續的focusable屬性,那該系統適用actionDone 動作,你也可以通過設置Android:imeOptions屬性使系統更改到其它值,如“actionSend”或“actionSearch”或禁止使用“actionNone”動作的默認行為。
如果您已指定鍵盤采用Android:imeOptions屬性(“actionSend”等)的操作方法,你可以使用TextView.OnEditorActionListener監聽事件行為。TextView.OnEditorActionListener接口提供了一個回調方法onEditorAction(),它通過輸入的動作ID,如IME_ACTION_SEND或IME_ACTION_SEARCH行為調用相關的動作類型方法。例如,你可以監聽用戶點擊鍵盤上的發送按鈕,如代碼清單2-14所示:
EditText editText = (EditText) findViewById(R.id.search); editText.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { boolean handled = false; if (actionId == EditorInfo.IME_ACTION_SEND) { // 發送用戶信息 handled = true; } return handled; } });
代碼清單2-14
如果鍵盤太大,系統將會合理分擔余下的應用程序(例如,當手機設備是橫向的)空間,然后全屏(“提取模式”)被觸發。在這種模式下,將在輸入框旁邊顯示按鈕,你可以通過設置imeActionLabel屬性來定制按鈕的文本,如代碼清單2-25所示:
<EditText android:id="@+id/launch_codes" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/enter_launch_codes" android:inputType="number" android:imeActionLabel="@string/launch" />
代碼清單2-15
效果圖如圖2-8所示:
圖2-8 android:imeActionLabel屬性案例
2.3.2提供自動完成提示
如果你想向用戶鍵入提供提示,您可以使用EditText的子類AutoCompleteTextView控件。為了實現自動完成,你必須指定一組( adndroid.widget.Adapter)文字提供建議。有幾種可用的適配器,匹配數據項,如從數據庫或一個數組獲取所需要匹配值。如圖2-9所示:
圖2-9 AutoCompleteTextView案例
下面的過程介紹了如何設置一個AutoCompleteTextView並使用ArrayAdapter適配器配置里面的所需的數組:
1. 添加AutoCompleteTextView到您的布局。這里是只是一個文本字段的布局,如代碼清單2-16所示:
<?xml version="1.0" encoding="utf-8"?> <AutoCompleteTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/autocomplete_country" android:layout_width="fill_parent" android:layout_height="wrap_content" />
代碼清單2-16
2. 定義一個數組,里面包含數組所需的子值。例如,這里是一個國家的名字,這是定義在一個XML資源文件(res/values/strings.xml)數組,如代碼清單2-17所示:
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="countries_array"> <item>Afghanistan</item> <item>Albania</item> <item>Algeria</item> <item>American Samoa</item> <item>Andorra</item> <item>Angola</item> <item>Anguilla</item> <item>Antarctica</item> ... </string-array> </resources>
代碼清單2-17
3. 在Acitivity中或Fragment中,建議使用下面的代碼操作適配器,如代碼清單2-18所示:
AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.autocomplete_country); String[] countries = getResources().getStringArray(R.array.countries_array); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, countries); textView.setAdapter(adapter);
代碼清單2-18
代碼中,創建一個countries的數組,並將ArrayAdapter適配器初始化,且將其綁定到simple_list_item_1文件布局中(這是由Android提供一個文本框綁定數據的文本列表)。然后AutoCompleteTextView屬性調用setAdapter()方法,將適配器添加其中。
2.4 復選框(CheckBox)
復選框允許用戶從列表中選擇一個或多個選項。通常,你應該在垂直的列表中顯示每一個選項。如圖2-10所示:
圖2-10 checkBox案例
當你要創建一個復選框時,你就必須要在你的布局文件中創建一個CheckBox字段。因為一組復選框選項允許用戶選擇多個選項,而且每個復選框分開管理,你必須為每一個選項注冊點擊監聽器。
2.4.1響應單擊事件
當用戶選擇一個復選框中的選項時,該復選框對象接收onClick事件。定義一個復選框的Click事件處理程序,需要在XML布局文件中的<CheckBox>元素中添加android:onClick屬性。這個屬性的值必須是你要調用的方法響應click事件的名稱。Activity界面將會響應該事件方法。例如,這里有幾組Checkbox對象列表,如代碼清單2-19所示:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <CheckBox android:id="@+id/checkbox_meat" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/meat" android:onClick="onCheckboxClicked"/> <CheckBox android:id="@+id/checkbox_cheese" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/cheese" android:onClick="onCheckboxClicked"/> </LinearLayout>
代碼清單2-19
在Activity中,將會響應Checkboxes字段中設置的方法,如代碼清代2-20所示:
public void onCheckboxClicked(View view) { boolean checked = ((CheckBox) view).isChecked(); switch(view.getId()) { case R.id.checkbox_meat: if (checked){} else{} break; case R.id.checkbox_cheese: if (checked){} else{} break; } }
代碼清單2-20
在方法中你必須聲明android:onClick屬性的方法,你在android聲明:onClick屬性必須嚴格按照上面顯示的屬性。具體來說,該方法和聲明按鈕一樣提示:如果你需要改變自己的單選按鈕狀態(如當加載一個保存CheckBoxPreference),使用setChecked(boolean)或toggle()方法。當然用代碼設置監聽事件也是有的,與按鈕類似就不在贅述。
FAQ群:213821767