第3章Android用户界面程序设计
视频讲解
3.1用户界面基础
用户界面(User Interface)是系统和用户间进行信息交换的媒介。Android实行界面设计者和程序开发者独立并行工作的方式,实现了界面设计和程序逻辑完全分离,不仅有利于后期界面修改中避免修改程序的逻辑代码,也有利于针对不同型号手机的屏幕分辨率调整界面尺寸时不影响程序的运行。
为了使界面设计和程序逻辑分离,Android程序将用户界面和资源从逻辑代码中分离出来,使用XML文件描述用户界面,资源文件独立保存在资源文件夹中。Android用户界面框架(Android UI Framework)采用MVC(ModelViewController)模型,为用户界面提供处理用户输入的控制器(controller)、显示图像的视图(view)和模型(model)。其中,模型是应用程序的核心,保存数据和代码。控制器、视图和模型的关系如图3.1所示。
MVC中的视图呈现用户界面,使用户在界面上进行输入,控制器能够接收并响应用户的动作,如按键和触摸屏幕等,并将这些动作作为一系列独立事件加入队列中,按照“先进先出”的规则将每个事件分配给对应的事件处理函数进行处理,根据处理结果更新模型。视图根据更新后的模型重新绘制界面并向用户展示,形成一个界面、数据更新的循环。
Android系统的界面元素以一种树形结构组织在一起,称为视图树,如图3.2所示。视图树由View和ViewGroup构成。View是一个重要的基类,所有界面上的可见元素都是View的子类,ViewGroup是能够承载多个View的显示单元,用于承载界面布局和具有原子特性的重构模块。
视图树绘制依据从上至下的原则绘制每个界面元素,且每个元素负责完成自身的绘制,如果元素包含子元素,则该元素通知其下所有子元素进行绘制。
图3.1MVC模型
图3.2视图树
Android用户界面是单线程用户界面,事件的获取和界面的屏幕绘制使用同一个线程,这样的好处是用户不需要在控制器和视图间进行同步,事件的处理完全按照队列顺序进行; 但单线程用户界面的缺点是如果事件函数过于复杂,可能导致用户界面失去响应,因此界面的事件响应函数应尽可能使用简短代码,或者将复杂工作交给后台线程处理。
3.2界 面 布 局
Android系统定义了6种基本摆放控件的规则,它们都间接或者直接继承ViewGroup类,下面介绍这几种布局规则。
Android移动网络程序设计案例教程(Android Studio版·第2版·微课视频版)
第
3
章Android用户界面程序设计
视频讲解
3.2.1框架布局
框架布局(FrameLayout)也叫帧布局,该布局上的控件放置在左上角位置,按放置的前后顺序逐一层叠摆放,后面的控件会遮盖之前的控件。
【例31】演示框架布局编程方法。
(1) 创建名为LayoutDemo的新项目,包名为edu.cqut.layoutdemo。切换到Android视图,右击res/layout文件夹,选择New→XML→Layout XML File,在弹出的对话框的Layout File Name栏填入layout_framelayout,在下方的Root Tag栏填入FrameLayout,创建一个框架布局文件。
(2) 在新创建的布局文件中放置一个ImageView和一个TextView控件,代码如下。
(3) 在java/edu.cqut.layoutdemo文件夹的MainActivity.java文件中修改与主Activity绑定的布局文件,修改后的代码如下。
setContentView(R.layout.layout_framelayout);
图3.3框架布局效果图
程序运行结果如图3.3所示,界面布局文件中后添加的文本框控件遮挡了之前的图像控件。
视频讲解
3.2.2线性布局
线性布局(LinearLayout)是将控件按照水平(horizontal)或垂直(vertical)两种方式排列,在布局文件中由android:orientation属性来控制排列方向。水平方向设置为android: orientation=“horizontal”,垂直方向设置为android: orientation=“vertical”。
【例32】演示线性布局编程方法。
(1) 打开LayoutDemo项目,右击res/layout文件夹,选择New→XML→Layout XML File,在弹出的对话框的Layout File Name栏填入layout_linearlayout,在下方的Root Tag栏填入LinearLayout,创建一个线性布局文件。
(2) 将新创建的布局文件的android:orientation属性设置为vertical,然后放置三个TextView控件,分别显示第一行、第二行和第三行,代码如下。
(3) 在MainActivity.java代码中修改与主Activity绑定的布局文件,修改后的代码如下。
setContentView(R.layout.layout_linearlayout);
图3.4线性布局效果图
程序运行结果如图3.4所示,控件按垂直方向逐个排列。
3.2.3相对布局
相对布局(RelativeLayout)是采用相对于其他控件位置的布局方式,该布局内的控件和其他控件存在相对关系,通常通过指定id关联其他控件,以右对齐、上对齐、下对齐或居中对齐等方式来排列控件。
视频讲解
相对布局属性较多,表3.1介绍了几种常用属性。
表3.1相对布局常用属性
属性描述
android:layout_alignParentTop="true|false"是否与父控件的顶部平齐
android:layout_alignParentBottom="true|false"是否与父控件的底部平齐
android:layout_alignParentLeft="true|false"是否与父控件的左边平齐
android:layout_alignParentRight="true|false"是否与父控件的右边平齐
android:layout_centerInParent="true|false"是否在父控件的中间位置
android:layout_centerInHorizontal="true|false"是否水平方向在父控件的中间
android:layout_centerInVertical="true|false"是否垂直方向在父控件的中间
android:layout_alignTop="@id/***"与相应id为***控件的顶部平齐
android:layout_alignBottom="@id/***"与相应id为***控件的底部平齐
android:layout_alignLeft="@id/***"与相应id为***控件的左边平齐
android:layout_alignRight="@id/***"与相应id为***控件的右边平齐
android:layout_above="@id/***"
在id为***控件的上面,该控件的底部与***顶部平齐
android:layout_blow="@id/***"
在id为***控件的下面,该控件的顶部与***底部平齐
android:layout_toRightOf="@id/***"
在id为***控件的右边,该控件的左边与***右边平齐
android:layout_toLeftOf="@id/***"
在id为***控件的左边,该控件的右边与***左边平齐
【例33】演示相对布局编程方法。
(1) 打开LayoutDemo项目,右击res/layout文件夹,选择New→XML→Layout XML File,在弹出的对话框的Layout File Name栏填入layout_relativelayout,在下方的Root Tag栏填入RelativeLayout,创建一个相对布局文件。
(2) 在该布局中放入三个TextView控件,并设置它们之间的相对位置关系,代码如下。
(3) 在MainActivity.java代码中修改与主Activity绑定的布局文件,修改后的代码如下。
setContentView(R.layout.layout_relativelayout);
图3.5相对布局效果图
程序运行结果如图3.5所示。由运行结果可以很明显地看出相对布局的特点,TextView1位于水平方向居中,TextView2位于TextView1下方,TextView3位于TextView2下方且右对齐。
视频讲解
3.2.4约束布局
约束布局(ConstrainLayout)是Android Studio 2.2中新增的功能之一。与传统的XML代码的界面编写方式相反,约束布局使用可视化的方式来编写界面,其结合Android Studio的布局编辑器通过拖曳控件完成布局,有利于解决布局嵌套过多的问题,是现在用得比较多的一种布局方式。
图3.6约束布局效果图
【例34】使用约束布局实现如图3.6所示的用户登录界面。
(1) 打开LayoutDemo项目,打开res/layout/activity_main.xml文件。该布局文件是项目创建的默认的布局文件,采用的是约束布局。
(2) 我们切换到activity_main.xml文件的Design视图,依次将左上Palette面板中的TextView、imageView、Plain Text和Button控件拖到左下ComPonent Tree面板中,每拖一个控件就通过中间的布局界面和右边的Attributes面板对该控件进行调整和属性设置,最后形成如图3.7所示的布局树和布局界面。
图3.7“用户登录”约束布局设计图
该布局的代码如下。
上述布局中的app:layout_constraintXXX_toXXX属性通过对控件的位置进行约束来实现其设置,这些属性的含义见表3.2。
表3.2约束布局的常用属性及含义
属性名
含义
layout_constraintTop_toTopOf
将所需视图的顶部与另一个视图的顶部对齐
layout_constraintTop_toBottomOf
将所需视图的顶部与另一个视图的底部对齐
layout_constraintBottom_toTopOf
将所需视图的底部与另一个视图的顶部对齐
layout_constraintBottom_toBottomOf
将所需视图的底部与另一个视图的底部对齐
layout_constraintLeft_toTopOf
将所需视图的左侧与另一个视图的顶部对齐
layout_constraintLeft_toBottomOf
将所需视图的左侧与另一个视图的底部对齐
layout_constraintLeft_toLeftOf
将所需视图的左边与另一个视图的左边对齐
layout_constraintLeft_toRightOf
将所需视图的左边与另一个视图的右边对齐
layout_constraintRight_toTopOf
将所需视图右对齐到另一个视图的顶部
layout_constraintRight_toBottomOf
将所需视图右对齐到另一个视图的底部
layout_constraintRight_toLeftOf
将所需视图的右边与另一个视图的左边对齐
layout_constraintRight_toRightOf
将所需视图的右边与另一个视图的右边对齐
(3) 为了给ImageView控件添加图像,在MainActivity.java文件中引入ImageView类。
import android.widget.ImageView;
(4) 修改与主Activity绑定的布局文件,代码如下。
setContentView(R.layout.activity_main);
ImageView iv = (ImageView)findViewById(R.id.imageView);
iv.setImageResource(R.mipmap.ic_launcher);
上述代码中findVewById()方法将id为imageView的控件与ImageView类的变量iv关联,然后通过ImageView类的方法setImageResource为imageView控件设置图像。
视频讲解
3.2.5表格布局
表格布局(TableLayout)是将布局页面划分为行、列构成的单元格。用标记表示单元格的一行,单元格的列数等于包含最多控件的TableRow的列数。直接在TableLayout中加的控件会占据一行。
TableLayout可设置的属性包括全局属性及单元格属性。
(1) 全局属性也即列属性,有以下3个参数。
① android:stretchColumns: 设置可伸展的列。该列可以沿行方向伸展,最多可占据一整行。
② android:shrinkColumns: 设置可收缩的列。当该列包含的控件的内容太多,已经挤满所在行时,该子控件的内容将沿列方向显示。
③ android:collapseColumns: 设置要隐藏的列。
示例:
android:stretchColumns="0" //第0列可伸展
android:shrinkColumns="1,2" //第1,2列皆可收缩
android:collapseColumns="*"// 隐藏所有列
说明: 列可以同时具备stretchColumns及shrinkColumns属性,若同时具备,那么当该列的内容很多时,将“多行”显示其内容(这里不是真正的多行,而是系统根据需要自动调节该行的layout_height)。
(2) 单元格属性,有以下2个参数。
① android:layout_column: 指定该单元格在第几列显示。
② android:layout_span: 指定该单元格占据的列数(未指定时为1)。
示例:
android:layout_column="1" //该控件显示在第1列
android:layout_span="2" //该控件占据2列
说明: 一个控件也可以同时具备这两个属性。
【例35】演示表格布局编程方法。
(1) 打开LayoutDemo项目,右击res/layout文件夹,选择New→XML→Layout XML File,在弹出的对话框的Layout File Name栏填入layout_tablelayout,在下方的Root Tag栏填入TableLayout,创建一个表格布局文件。
(2) 创建6个TextView控件,分别显示其坐标,代码如下。
图3.8表格布局效果图
(3) 在MainActivity.java代码中修改与主Activity绑定的布局文件,修改后的代码如下。
setContentView(R.layout.layout_tablelayout);
运行结果如图3.8所示。由运行结果很容易看出表格布局的特点,各控件分布于一个表格内。
视频讲解
3.2.6网格布局
网格布局(GridLayout)是Android 4.0以上版本出现的,网格布局使用虚细线将布局划分为行、列和单元格,也支持控件在行、列上交错排列。
首先它与LinearLayout布局一样,也分为水平和垂直两种方式,默认是水平布局,一个控件挨着一个控件从左到右依次排列,但是通过指定android:columnCount属性设置列数后,控件会自动换行进行排列。另一方面,对于GridLayout布局中的控件,默认按照wrap_content的方式设置其显示。
其次,若要指定某控件显示在固定的行或列,只需设置该控件的android:layout_row和android:layout_column属性即可。但是需要注意: android:layout_row="0"表示从第一行开始,android:layout_column="0"表示从第一列开始,这与编程语言中一维数组的赋值情况类似。
最后,如果需要设置某控件跨越多行或多列,只需将该控件的android:layout_rowSpan或者layout_columnSpan属性设置为数值,再设置其layout_gravity属性为fill即可,前一个设置表明该控件跨越的行数或列数,后一个设置表明该控件填满所跨越的整行或整列。
3.2.7布局的混合使用
单独使用某一种布局很难做出复杂美观的界面,所以布局往往不是单独使用的,而是恰当的布局嵌套使用,相同的布局可以嵌套,不同的布局也可以嵌套,如3.4.2节的主界面设计。
视频讲解
3.3界面常用控件
3.3.1TextView和EditText
TextView是用于显示字符的控件,类似于C#和Java语言中的Label控件,但它支持显示多行文本及自动换行。EditText则是用来输入和编辑字符的控件,具有编辑功能,包括Plain Text、Password、Password(Numeric)、Email、Phone、Postal Address、Multiline Text、Time、Date、Number、Number(Signed)、Number(Decimal)等控件。这两个控件经常一起使用。
该布局创建了TextView和EditText控件,分别声明了TextView和EditText的ID,以便于在代码中引用相应的控件对象。“@+id/TextView1”表示所设置的ID值,@表示后面的字符串是ID资源,加号(+)表示需要建立新资源名称,并添加到R.java文件中,但当R.java中已经存在同名变量TextView1时,该控件会使用这个已存在的值。android:layout_margin="20dp"表示设置控件四周的空隙尺寸为20个设备独立像素(device independent pixels)。EditText中的android:textSize="18sp"表示文字尺寸大小为18个缩放独立像素(scaleindependent pixels)。sp主要用作字体的单位,用此单位设置文字大小,可以在不同像素密度的屏幕上进行同比例的扩大缩小。android:ems是一种长度单位,表示一个字符的标准长度,适用于动态布局。如果系统的默认字体大小为1ems,则android:ems="10"表示该控件可包含10个字符的大小,并且,如果窗口变大,该控件也会自动变大。android:hint属性用于设置EditText控件输入框中的提示文字,这里取strings.xml文件中edittext_name元素的值,而android:autofillHints属性用于设置该控件的自动填写文字。如果EditText控件缺少这两个属性,则控件在“Design”视图中会出现警告符号。android:inputType设置编辑框输入的数值属性,常用数值属性及含义见表3.3。
表3.3EditText的android:inputType属性的值及含义
属性值
含义
属性值
含义
none
/
text
文本
textCapCharacters
字母大写
textCapWords
首字母大写
textCapSentences
仅第一个字母大写
textAutoCorrect
自动完成
textMultiLine
多行输入
textImeMultiLine
输入法多行(如果支持)
textNoSuggestions
不提示
textUri
网址
textEmailAddress
电子邮件地址
textEmailSubject
邮件主题
textShortMessage
短信息
textLongMessage
长信息
textPersonName
人名
textPostalAddress
地址
textPassword
密码
textVisiblePassword
可见密码
textWebEditText
作为网页表单的文本
textFilter
文本筛选过滤
textPhonetic
拼音输入
number
数字
numberSigned
带符号数字格式
numberDecimal
带小数点的浮点格式
phone
拨号键盘
datetime
时间日期
Date
日期键盘
time
时间键盘
为了在代码中引用activity_main.xml中设置的控件,首先需要在MainActivity.java代码中引入android.widget开发包,然后使用findViewById()函数通过ID引用该控件,并把该控件赋值给创建的控件对象。该函数可以引用任何在XML文件中定义过ID的控件。setText()函数用来设置控件显示的内容。
package edu.cqut.commoncontroldemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.*;
import android.view.View;
public class MainActivity extends AppCompatActivity {
EditText editText = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText)findViewById(R.id.editTextDemo);
editText.setText("请输入");
}
}
程序运行结果如图3.9所示。
图3.9TextView和EditView控件运行效果
视频讲解
3.3.2Button和ImageButton
Button是常用的普通按钮控件,用户能够在该控件上单击,引发相应的响应事件。如果需要在按钮上显示图像,则可以使用ImageButton控件。
【例36】演示Button和ImageButton控件编写方法。
(1) 在CommonControlDemo项目的activity_main.xml中分别添加Button和ImageButton控件,代码如下。
(2) Android支持多种图形格式,如png、ico、jpg等,本例使用jpg格式。在Android Studio的Project视图中将green_bk.jpg文件复制到app/src/res/mipmaphdpi文件夹中,更新R.java文件,选择菜单中的Build→Rebuild Project选项进行R.java更新。如果R.java文件不更新,则无法在代码中使用该资源。
(3) 在MainActivity.java代码中引用两个按钮,并让ImageButton显示图像green_bk.jpg内容。
ImageButton imageButton = (ImageButton)findViewById(R.id.imageButton1);
imageButton.setImageResource(R.drawable.green_bk);
Button button = (Button)findViewById(R.id.button_OK);
(4) 为了使两个按钮能够响应单击事件,需要在onCreate()函数中为它们分别添加单击事件监听器,其代码如下。
//添加单击button事件的监听器
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
editText.setText("你单击了button按钮");
}
});
//添加单击imageButton事件的监听器
imageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
editText.setText("你单击了imageButton按钮");
}
});
图3.10Button和ImageButton运行效果
按钮对象通过调用setOnClickeListener()函数,注册单击事件(Click)的监听器View.OnClickListener(),该监听器接口中仅包含了onClick()抽象函数。我们实现(Override)该函数。当按钮控件从Android界面框架中接收到事件后,首先检查这个事件是否是单击事件,如果是,同时Button又注册了监听器,则会调用该监听器中实现的onClick()函数。程序运行结果如图3.10所示。
3.3.3CheckBox和RadioButton
CheckBox是可以同时选择多个选项的控件,而RadioButton则是仅可以选择一个选项的控件。RadioGroup是RadioButton的承载体,程序运行时不可见。在一个RadioGroup中,用户仅能选择其中一个RadioButton。
【例37】演示CheckBox和RadioButton控件编写方法。
(1) 在CommonControlDemo项目的activity_main.xml中分别添加CheckBox和RadioButton控件的代码如下。
(2) 在MainActivity.java代码中引用创建的CheckBox和RadioButton控件,并在onCreate()函数中为它们添加单击事件监听器,代码如下。
public class MainActivity extends AppCompatActivity
{
...
CheckBox checkBox1 = null;
CheckBox checkBox2 = null;
RadioButton radioButton1 = null;
RadioButton radioButton2 = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
checkBox1 = (CheckBox)findViewById(R.id.checkBox1);
checkBox2 = (CheckBox)findViewById(R.id.checkBox2);
radioButton1 = (RadioButton)findViewById(R.id.radioButton1);
radioButton2 = (RadioButton)findViewById(R.id.radioButton2);
//将多个CheckBox控件注册到一个选择单击事件的监听器上
CheckBox.OnClickListener checkboxListener = new CheckBox.OnClickListener() {
@Override
public void onClick(View v) {
if (checkBox1.isChecked() && checkBox2.isChecked())
editText.setText("你选择了多选框1和多选框2");
else if (checkBox1.isChecked())
editText.setText("你选择了多选框1");
else if (checkBox2.isChecked())
editText.setText("你选择了多选框2");
else
editText.setText("");
}
};
checkBox1.setOnClickListener(checkboxListener);
checkBox2.setOnClickListener(checkboxListener);
//将多个RadioButton控件注册到一个单击事件的监听器上
RadioButton.OnClickListener radioButtonListener = new RadioButton.OnClickListener()
{
@Override
public void onClick(View v){
if (radioButton1.isChecked() && radioButton2.isChecked())
editText.setText("你选择了单选框1和单选框2");
else if (radioButton1.isChecked())
editText.setText("你选择了单选框1");
else if (radioButton2.isChecked())
editText.setText("你选择了单选框2");
else
editText.setText("");
}
};
radioButton1.setOnClickListener(radioButtonListener);
radioButton2.setOnClickListener(radioButtonListener);
}
}
图3.11CheckBox和RadioButton运行效果
CheckBox和RadioButton控件运行效果如图3.11所示。
视频讲解
3.3.4Spinner和ListView
Spinner是从多个选项中选择一个选项的控件,类似于桌面程序的组合框(ComboBox),但没有组合框的下拉菜单,而是使用浮动菜单为用户提供选择。ListView是用于垂直显示的列表控件,如果显示内容过多,则会出现垂直滚动条。
这两个控件在界面设计中经常使用,其原因是它们能够通过适配器将数据和显示控件绑定,且支持单击事件,可以用少量代码实现复杂的选项功能。Spinner和ListView控件效果如图3.12所示。
Spinner和ListView的直接父类是ViewGroup,其中定义了子View的排列规则。Spinner及ListView和所要展示的内容(即数据源)之间需要Adapter(适配器)来实现。Adapter是一个桥梁,如图3.13所示,对ListView和Spinner的数据进行管理。
图3.12Spinner和ListView
控件
图3.13数据源、Adapter和列表间的关系图
Adapter是一个接口,图3.14列出了Android中与Adapter有关的所有接口、类的完整层级图,比较常用的有BaseAdapter、SimpleAdapter、ArrayAdapter、SimpleCursorAdapter等。其中BaseAdapter是一个抽象类,继承它需要较多的方法,所以具有较高的灵活性。ArrayAdapter支持泛型操作,最为简单,只能展示一行文本。SimpleAdapter有最好的扩充性,可以自定义各种效果。
图3.14Android中所有的Adapter一览
Spinner和ListView显示前要使用setAdapter()方法,ListView本身继承自ViewGroup,只设定它里面的View的排列规则,不设定其是什么样的,而View是什么样的需要靠ListAdapter里面的getView方法来确定,只要设置不同的ListAdapter实例对象,就会生成不一样的ListView。
【例38】使用ArrayAdapter演示Spinner和ListView控件编程方法。
(1) 在CommonControlDemo项目的activity_main.xml中分别添加Spinner和ListView控件的代码如下。
(2) 在MainActivity.java代码中引用创建的Spinner控件,并在onCreate()函数中添加单击子项选中事件监听器,代码如下。
spinner = (Spinner)findViewById(R.id.spinner1);
List listspinner = new ArrayList();
listspinner.add("Spinner子项1");
listspinner.add("Spinner子项2");
//使用ArrayAdapter数组适配器将界面控件和底层数据绑定在一起,即Spinner和ArrayList绑定
ArrayAdapter adapter1 = new ArrayAdapter(this,
android.R.layout.simple_spinner_item, listspinner);
//设置Spinner浮动菜单显示方式
adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter1);//完成绑定
//添加单击spinner选项的事件监听器
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView>parent, View view, int position, long id)
{
editText.setText(((TextView)view).getText());
}
@Override
public void onNothingSelected(AdapterView> arg0)
{
editText.setText("");
}
});
上面代码中android.R.layout.simple_spinner_dropdown_item为Spinner浮动菜单显示的方式之一,效果如图3.15所示。另一种浮动菜单是android.R.layout.simple_ spinner_item,显示效果如图3.16所示。
图3.15Spinner的dropdown菜单
图3.16Spinner的item菜单
AdapterView.OnItemSelectedListener()是Spinner子项选中事件监听器,需要实现onItemSelected()和onNothingSelected()两个函数。其中,onItemSelected()有4个参数,参数parent表示控件适配器,这里就是Spinner; 参数view表示适配器内部被选中的控件,即Spinner中的子项; 参数position表示选中的子项的位置; 参数id表示选中的子项的行号。
(3) 在MainActivity.java代码中引用创建的ListView控件,并在onCreate()函数中添加单击子项选中事件监听器,代码如下。
listview = (ListView)findViewById(R.id.listView1);
List list = new ArrayList();
for (int i=1; i<10; i++)
list.add("ListView子项"+i);
//使用ArrayAdapter数组适配器将界面控件和底层数据绑定在一起,即ListView和ArrayList绑定
ArrayAdapter adapter2 = new ArrayAdapter(this,
android.R.layout.simple_list_item_1, list);
listview.setAdapter(adapter2);//完成绑定
//添加单击ListView选项的事件监听器
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView>parent, View view, int position, long id)
{
editText.setText(((TextView)view).getText());
}
});
为ListView添加了10个子项,这样当屏幕显示不下ListView控件列表时,会出现垂直滑块,通过上下滑动,可以显示其余子项。代码中onItemClick()函数的参数含义与之前onItemSelected()函数参数含义相同。图3.17是CommonControlDemo项目的效果图。
视频讲解
3.3.5自定义列表
对于不同的适配器类型,ArrayAdapter是最简单的一种,就如例38演示的一样,只能显示一行文字,而SimpleAdapter的扩展性最好,可以定义各种各样的布局,也可以放上ImageView,还可以放上Button和CheckBox等,因此可以用它来生成自定义列表。下面的例子演示了如何生成一个带图片的菜单列表。
【例39】使用SimpleAdapter演示自定义列表编程方法。
图3.18是例39的运行效果,下面来实现该列表。
创建名为CustomListViewDemo的新项目,包名为edu.cqut.customlistviewdemo。切换到Project视图。
(1) 进入项目的app\src\main\res目录,右击res文件夹,在弹出菜单中选择New→Directory,创建raw文件夹,在其中存放4张菜品图片。
(2) 在res\layout文件夹中创建名为listitem.xml的布局文件。该布局文件采用混合线性布局,用于定义ListView中每行显示的控件,依次为菜品图片、菜品名称和菜品简介。代码如下。
图3.17CommonControlDemo效果图
图3.18自定义列表运行效果
(3) 修改layout文件夹中的activity_main.xml的布局文件,代码如下。
该布局文件显示菜单页面,第一行为TableRow布局,其中TextView控件用于显示标题,TableRow布局的下一行为ListView控件,该控件显示各个具体的菜品,而这个ListView控件的布局将使用listitem.xml文件。
(4) 在项目app\src\main\java\edu.cqut.customlistviewdemo文件夹中添加名为Dish.java的Java文件,定义用于菜品Dish类。
public class Dish
{
public String mName;//菜名
public int mImage; //菜品图像
public String mInfo;//介绍
}
(5) 在MainActivity.java文件的MainActivity类中创建适配器和数据源。
static List