第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()方法。当然用代码设置监听事件也是有的,与按钮类似就不在赘述。