首页计算机计算机软件Android开发工程师教程 03 第三章 用户界面基本组件.pptx

03 第三章 用户界面基本组件.pptx

页数:71页文件大小:2.98 MB来源: Android开发工程师教程ppt课件

本课件以案例讲解界面基本组件,先说明图形界面的MVC设计模式与常见系统组件,再通过登录界面、图片浏览器、注册界面、日期时间、导航条、下载进度条、考试系统界面与消息提醒等案例给出布局与事件监听代码。

Android开发工程师教程第三章封面页,标示本篇主题为Android用户界面基本组件开发
第三章教学目标页,要求理解图形界面MVC设计模式并掌握TextView、Button、ListView等组件与事件处理
第三章目录页,列出用户界面基础、登录界面、图片浏览器、注册界面等十一个案例与小结
查看本课件的文字版(共 71 页,供检索与复制)

第1页:第三章用户界面基本组件封面

Android开发工程师教程第三章用户界面基本组件开发基础篇

第2页:教学目标

教学目标

理解Android系统中图形界面的MVC设计模式

掌握TextView、EditText、Button、ImageButton、RadioButton、CheckBox、DatePicker、TimePicker、ImageView、ListView、TabHost等基本组件的使用方法。

掌握基本组件的事件处理。

第3页:本章目录

本章目录

  • 用户界面基础
  • 友好登录界面的设计与实现
  • 图片浏览器的设计与实现
  • 注册界面的设计与实现
  • 设置日期和时间的设计与实现
  • 导航条的设计与实现
  • 模拟文件下载进度条的设计与实现
  • 考试系统界面的设计与实现
  • 模拟PPS(网络电视)消息提醒的设计与实现
  • 本章小结
  • 项目实训

第4页:MVC设计模式

用户界面基础

MVC: Android图形用户界面框架基于MVC(Model-View-Controller,模型—视图—控制器)设计模式

  • 模型(Model)是应用程序的核心,用于完成实际的工作。模型有可能是保存在本地数据库中的歌曲以及播放这些歌曲的代码,也有可能是程序中用于保存联系人信息的列表以及给联系人拨打电话或者发送短信的代码。
  • 视图(View)是应用程序给手机用户的各种信息反馈的组成。视图负责手机屏幕的渲染、声音的播放以及触觉反馈(通过振动)等。Android用户界面的图形部分是由一组树状的图形元素构成的,它们都是View类的子类。每一个图形元素都代表了手机屏幕上位于它的父元素内部的一个矩形区域,而该图形元素树的根就是应用程序的窗口对象。
  • 控制器(Controller)是一个应用程序中用于处理外部输入的部分,如用户的按键操作、屏幕单击和一个来电等。对于外部的输入,Android平台是通过事件队列来实现的,每一个外部的输入动作都用队列中唯一的一个事件来表示,系统会按照顺序从队列中取出每一个事件并将它们分发给特定的应用程序进行处理。

第5页:常见系统组件

用户界面基础

常见的系统组件包括TextView、EditText、Button、ImageButton、RadioButton、CheckBox、ToggleButton、DigitalClock、DatePicker、TimePicker、ImageView、ListView、ProgressBar、TabHost、Toast、Notification。

第6页:登录界面章节目录

本章目录

  • 友好登录界面的设计与实现
  • 用户界面基础
  • 图片浏览器的设计与实现
  • 注册界面的设计与实现
  • 设置日期和时间的设计与实现
  • 导航条的设计与实现
  • 模拟文件下载进度条的设计与实现
  • 考试系统界面的设计与实现
  • 模拟PPS(网络电视)消息提醒的设计与实现
  • 本章小结
  • 项目实训

第7页:登录界面任务

友好登录界面的设计与实现

任务:通过TextView、EditText、Button组件,设计一个良好的手机登录界面。

第8页:LinearLayout嵌套布局

友好登录界面的设计与实现

预备知识:整个界面是垂直方向的LinearLayout布局。

每一行的组件是水平方向的LinearLayout布局,代码如下所示:

<LinearLayoutandroid:id="@+id/linear1"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal">//控制布局方向为水平方向…//此处添加需要显示的组件</LinearLayout>

第9页:EditText与Button的继承关系

友好登录界面的设计与实现

预备知识:EditText和Button组件都继承于TextView,可以说EditText是一个具有编辑功能的TextView。TextView提供了大量的XML属性,这些属性大部分既可以用于TextView,又可适用于EditText和Button,仅有少部分属性只适用于其中之一。TextView的常用属性见表3-1

第10页:登录界面布局代码

友好登录界面的设计与实现

登录界面的设计,因为每一行的布局是一样的,所以此处只给出整个界面的布局,和输入“学号”这行的布局代码。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><!--通过android:text实现TextView显示的文本--><!--通过android:ellipsize实现跑马灯效果--><!--通过android:textSize实现控制字体大小--><!--通过android:marqueeRepeatLimit设置跑马灯效果循环无限次--><TextViewandroid:id="@+id/firstView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="欢迎您登录成绩查询系统,祝你好运哦!!!!!"android:textSize="20sp"android:singleLine="true"android:ellipsize="marquee"android:marqueeRepeatLimit="marquee_forever"android:focusable="true"android:focusableInTouchMode="true"android:scrollHorizontally="true" /><LinearLayout接下页

第11页:登录界面布局代码续

友好登录界面的设计与实现

android:id="@+id/linear1"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><!--通过android:textColor设置字体颜色--><!--通过android:textStyle设置字形--><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="学号:"android:textSize="20sp"android:textColor="#00ff00"android:textStyle="bold"/><!--通过android:hint设置输入提示信息--><!--通过android:inputType设置数字输入格式--><EditTextandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:hint="请输入学号"android:inputType="number"/></LinearLayout>...............<Buttonandroid:id="@+id/loginBtn"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="登录"android:textSize="20sp"/></LinearLayout>

第12页:登录界面变量定义

友好登录界面的设计与实现

登录界面的功能实现:

使用如下语句定义布局文件中的组件:

private TextView firstView;private EditText numberET,nameET,passwordET;private Button loginBtn;private String number,name,password;

为了在代码中使用布局文件定义的组件,必须使用findViewById()方法,例如,要引用第一个TextView,需要使用firstView=(TextView)findViewById(R.id.firstView)语句来获取到TextView对象。

第13页:登录按钮判断代码

友好登录界面的设计与实现

当点击登录按钮时判断输入的学号、姓名、密码是否为“001”,是则显示登录成功,否则显示输入有误,重新输入。详细设计代码如下:

public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);firstView = (TextView)findViewById(R.id.firstView);//根据ID获取到TextView对象numberET = (EditText)findViewById(R.id.numberET);//根据ID获取到EditText对象nameET = (EditText)findViewById(R.id.nameET);passwordET = (EditText)findViewById(R.id.passwordET);loginBtn = (Button)findViewById(R.id.loginBtn);//根据ID获取到Button对象loginBtn.setOnClickListener(new OnClickListener(){//对Button实现单击事件监听@Overridepublic void onClick(View v){//设置单击Button后要执行的操作number = numberET.getText().toString();//获取文本框输入的内容name = nameET.getText().toString();password = passwordET.getText().toString();if (number.equals("001")&& name.equals("001")&& password.equals("001")){firstView.setText(name + "同学您已经登录成绩查询系统!");} else {firstView.setText("您的输入有误,请重新输入!!!");}}});}

第14页:图片浏览器章节目录

本章目录

  • 图片浏览器的设计与实现
  • 用户界面基础
  • 友好登录界面的设计与实现
  • 注册界面的设计与实现
  • 设置日期和时间的设计与实现
  • 导航条的设计与实现
  • 模拟文件下载进度条的设计与实现
  • 考试系统界面的设计与实现
  • 模拟PPS(网络电视)消息提醒的设计与实现
  • 本章小结
  • 项目实训

第15页:ImageButton与图像视图

图片浏览器的设计与实现

预备知识

Android系统为了满足用户显示图像按钮的需要,提供了ImageButton组件。ImageButton直接继承于ImageView。ImageView组件继承自View组件,它主要用于显示图像,图像可能来自一个文件、ContentProvider或图形对象等资源

ImageView常用属性和功能见表3-2

ImageView中属性ScaleType的属性值如表3-3所示

第16页:ImageButton的selector

图片浏览器的设计与实现

ImageButton可以通过selector来设置不同状态下按钮的背景图片,这种方式需要在res/drawable目录下新增一个XML文件,在XML文件中设置state_pressed、state_selected、state_focused等几种状态。这个XML标签由

<selector>标签组成,<selector>标签中可以有多个<item>标签,在<item>标签中可以定义不同状态下显示的不同图片,然后通过ImageButton属性android:src="@drawable/ResourceID"引入该<selector>标签。selector.xml中的代码如下所示:<?xml version="1.0" encoding="UTF-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"><!—单击按钮时,ImageButton上显示的图片--><item android:state_pressed="true" android:drawable="@drawable/preb"/><!--正常情况下,ImageButton上显示的图片--><item android:state_pressed="false" android:drawable="@drawable/preg"/></selector>

第17页:导入图片到drawable

图片浏览器的设计与实现

预先把需要用的图片,导入到drawable目录下,如图3.5所示。

第18页:图片浏览器布局代码

图片浏览器的设计与实现

本界面中主要用到了ImageView和ImageButton控件,布局设计代码:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/showView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="@string/hello_world"/><ImageViewandroid:id="@+id/imageView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:scaleType="centerCrop"android:src="@drawable/pic1"/><LinearLayoutandroid:id="@+id/linear1"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginTop="25dip"android:orientation="horizontal"><ImageButtonandroid:id="@+id/preBut"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="30dip"android:src="@drawable/selectora"/><ImageButtonandroid:id="@+id/nextBut"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="100dip"android:src="@drawable/selectorb"/></LinearLayout></LinearLayout>

第19页:图片浏览器变量定义

图片浏览器的设计与实现

当点击向左和向右的ImageButton分别实现前翻后后翻图片,图片预先用一个数组存储,遍于功能实现。

预先定义的控件变量如下:

private ImageButton preBtn,nextBtn;private ImageView imageView;private int currentImgId=0;//记录当前ImageView中显示图片的IDint imgID[]={R.drawable.pic1,R.drawable.pic2,R.drawable.pic3};//存储ImageView显示的图片的ID

第20页:图片浏览器功能代码

图片浏览器的设计与实现

详细设计代码如下:

public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);imageView=(ImageView)findViewById(R.id.imageView);preBtn=(ImageButton)findViewById(R.id.preBut);nextBtn=(ImageButton)findViewById(R.id.nextBut);preBtn.setOnClickListener(new ButtonListener());nextBtn.setOnClickListener(new ButtonListener());}class ButtonListener implements OnClickListener{@Overridepublic void onClick(View v){// TODO Auto-generated method stubif(v==preBtn){//如果单击的是“上一张”按钮currentImgId=(currentImgId-1+imgID.length)%imgID.length;//计算图片在数组中的下标imageView.setImageResource(imgID[currentImgId]);//设置ImageView显示的图片}if(v==nextBtn){//如果单击的是“下一张”按钮currentImgId=(currentImgId+1)%imgID.length;//计算图片在数组中的下标imageView.setImageResource(imgID[currentImgId]);//设置ImageView显示的图片}}}

第21页:注册界面章节目录

本章目录

  • 注册界面的设计与实现
  • 用户界面基础
  • 友好登录界面的设计与实现
  • 图片浏览器的设计与实现
  • 设置日期和时间的设计与实现
  • 导航条的设计与实现
  • 模拟文件下载进度条的设计与实现
  • 考试系统界面的设计与实现
  • 模拟PPS(网络电视)消息提醒的设计与实现
  • 本章小结
  • 项目实训

第22页:RadioButton与CheckBox

注册界面的设计与实现

预备知识:本设计中主要用到了RadioButton、CheckBox组件、以及Toast的使用。

在Android系统中,RadioButton与CheckBox都是Button的子类,所以继承了Button的各种属性,而且还多了一个可选中的功能。

  • RadioButton单选按钮是一种双状态的按钮,有checked和unchecked两种状态。RadioButton通常都是和RadioGroup结合使用,RadioGroup是用于创建一组选中状态相互排斥的单选按钮组,是可以容纳多个RadioButton的容器。在一个RadioGroup中最多只有一个RadioButton被选中,如果一个组中选中了一个RadioButton,会自动取消其他按钮的选中状态。不同的RadioGroup中的RadioButton互不相干,即如果组A中有一个RadioButton被选中了,组B中依然可以有一个RadioButton被选中。一般情况下,一个RadioGroup中至少有两个RadioButton。
  • CheckBox可以让用户选择一个以上的选项,为了确定用户是否选择了某一项,就需要对每一个CheckBox设置事件监听器,CheckBox需要实现的是android.widget.CompoundButton. OnCheckedChangeListener()接口,通过其中的ChekBox.isChecked()方法判断该选项是否被选中,true表示选中,false表示未选中。

第23页:Toast组件说明

注册界面的设计与实现

预备知识:

在本案例中,测试对RadioButton和CheckBox事件监听是否产生相应的效果,运用Toast组件来显示结果。

Toast组件是一种给用户提示信息的视图,该视图以浮于应用程序之上的形式呈现给用户,而且显示的时间有限,过一段时间后自动消失。因为它并不获得焦点,所以即使用户正在输入信息也不会受到影响。Toast可以自定义提示框的位置、显示的文字内容、显示的图标等信息。

创建一个Toast涉及的常量有以下两种。

  • (1)LENGTH_LONG:表示持续显示视图或文本较长时间。
  • (2)LENGTH_SHORT:表示持续显示视图或文本较短时间

Toast常用方法如表3-4所示。

gravity的值及说明如表3-5所示。

第24页:Toast变量定义

注册界面的设计与实现

预备知识

  • 默认Toast、自定义Toast显示位置、带图标的Toast的实现。
  • 界面中主要运用了3个按钮,点击3个按钮分别对应不同的Toast。
  • 变量定义如下:
private Button firstBtn, secondBtn,thirdBtn;
private Toast toast;

第25页:Toast实现代码

注册界面的设计与实现

Toast的详细实现代码:

protected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);firstBtn = (Button)findViewById(R.id.firstBtn);secondBtn =(Button)findViewById(R.id.secondBtn);thirdBtn = (Button)findViewById(R.id.thirdBtn);//下面是多个按钮注册到同一个事件监听器上firstBtn.setOnClickListener(new BtnListener());secondBtn.setOnClickListener(new BtnListener());thirdBtn.setOnClickListener(new BtnListener());}class BtnListener implements OnClickListener {@Overridepublic void onClick(View v){switch (v.getId()){case R.id.firstBtn:Toast.makeText(MainActivity.this, "这是默认样式的toast",Toast.LENGTH_LONG).show();return;case R.id.secondBtn:toast = Toast.makeText(MainActivity.this, "这是自定义位置的toast",Toast.LENGTH_LONG);//调用setGravtity()方法,设置toast的显示位置toast.setGravity(Gravity.CENTER, 0, 0);//显示toasttoast.show();return;case R.id.thirdBtn:toast = Toast.makeText(MainActivity.this, "这是带图标的toast",Toast.LENGTH_LONG);toast.setGravity(Gravity.CENTER, 0, 0);//获取Toast的View对象LinearLayout toastView = (LinearLayout)toast.getView();//创建ImageView对象ImageView image = new ImageView(MainActivity.this);//设置ImageView的背景图片image.setImageResource(R.drawable.icon);//将ImageView添加到View上toastView.addView(image);//将View显示在Toast上toast.setView(toastView);toast.show();return;}}}

第26页:注册界面布局代码

注册界面的设计与实现

注册界面布局设计:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="请输入您的用户名:"/><EditTextandroid:id="@+id/editText1"android:layout_width="fill_parent"android:layout_height="wrap_content"android:hint=" "/><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="请选择您的性别:"/><RadioGroupandroid:id="@+id/radioGroup1"android:orientation="horizontal"android:layout_width="wrap_content"android:layout_height="wrap_content"><RadioButtonandroid:id="@+id/maleButton"android:text="男"android:layout_width="wrap_content"android:layout_height="wrap_content"/><RadioButtonandroid:id="@+id/femaleButton"android:text="女"android:layout_width="wrap_content"android:layout_height="wrap_content"/></RadioGroup><TextViewandroid:id="@+id/textView3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="请选择您的爱好:"/><CheckBoxandroid:id="@+id/singBox"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="唱歌"/><CheckBoxandroid:id="@+id/danceBox"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text=“跳舞”/>。。。。。。。

第27页:注册界面变量定义

注册界面的设计与实现

基本的变量定义如下:privateRadioGroupgenderGroup;//定义单选按钮组privateRadioButtonmaleBtn,femaleBtn;privateCheckBoxsingCheckBox,danceCheckBox,drawCheckBox;

通过findViewById()方法找出相应组件的代码genderGroup= (RadioGroup)findViewById(R.id.radioGroup1);maleBtn= (RadioButton)findViewById(R.id.maleButton);femaleBtn= (RadioButton)findViewById(R.id.femaleButton);singCheckBox= (CheckBox)findViewById(R.id.singBox);danceCheckBox= (CheckBox)findViewById(R.id.danceBox);drawCheckBox= (CheckBox)findViewById(R.id.drawBox);

第28页:单选按钮监听事件

注册界面的设计与实现

本案例中对于性别单选按钮监听事件使用android.widget.RadioGroup.OnCheckedChangeListenerOnCheckedChangedListener()的匿名内部类实现。主要代码如下:genderGroup.setOnCheckedChangeListener(new OnCheckedChangeListener(){

@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId){String sexString = "";//定义显示性别的字符串变量if (maleBtn.getId()== checkedId){//根据checkedId判断用户的选项sexString = sexString + maleBtn.getText();//调用getText()方法获得按钮文本} else if (femaleBtn.getId()== checkedId){sexString = sexString + femaleBtn.getText();}Toast.makeText(MainActivity.this, "您选择的性别是:" + sexString,Toast.LENGTH_LONG).show();}});

第29页:复选按钮监听事件

注册界面的设计与实现

对于复选按钮事件监听使用android.widget.CompoundButton.OnCheckedChangeListener()接口的单独类实现,代码如下所示;class Listener

implements android.widget.CompoundButton.OnCheckedChangeListener {@Overridepublic void onCheckedChanged(CompoundButton buttonView,boolean isChecked){String str = "";//定义显示爱好的字符串变量//调用isChecked()方法,判断哪个选项被选中if (singCheckBox.isChecked()){str = str + singCheckBox.getText();}if (danceCheckBox.isChecked()){str = str + danceCheckBox.getText();}if (drawCheckBox.isChecked()){str = str + drawCheckBox.getText();}Toast.makeText(MainActivity.this, "您选择的爱好是:" + str,Toast.LENGTH_LONG).show();}}

第30页:日期时间章节目录

本章目录

  • 设置日期和时间的设计与实现
  • 用户界面基础
  • 友好登录界面的设计与实现
  • 注册界面的设计与实现
  • 图片浏览器的设计与实现
  • 导航条的设计与实现
  • 模拟文件下载进度条的设计与实现
  • 考试系统界面的设计与实现
  • 模拟PPS(网络电视)消息提醒的设计与实现
  • 本章小结
  • 项目实训

第31页:DatePicker与时间选择器

设置日期和时间的设计与实现

预备知识:

  • DatePicker继承自FrameLayout类。DatePicker组件的主要功能是向用户提供包含年、月、日的日期数据并允许用户对其修改。如果需要捕获用户修改日期选择组件中的数据事件,需要为DatePicker添加OnDateChangedListener监听器。
  • TimePicker也继承自FrameLayout类。TimePicker组件向用户显示一天中的时间(可以为24小时制,也可以为AM/PM制),并允许用户进行选择。如果要捕获用户修改时间数据的事件,需要为TimePicker添加OnTimeChangedListener监听器。

第32页:日期时间界面代码

设置日期和时间的设计与实现本案例中运用了DatePicker和TimePicker,以及两个TextView组件,两个TextView组件分别用来显示DatePicker和TimePicker上设置的日期和时间。界面设计l代码如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!--DatePicker组件--><DatePickerandroid:id="@+id/datePicker"android:layout_width="wrap_content"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/dateShow"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="显示设置的日期"/><!--TimePicker组件--><TimePickerandroid:id="@+id/timePicker"android:layout_width="wrap_content"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/timeShow"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="显示设置的时间"/></LinearLayout>

第33页:日期时间变量定义

设置日期和时间的设计与实现

详细功能实现部分:

变量的定义如下:

private DatePicker my_datePicker;private TimePicker my_timePicker;private TextView dateView, timeView;private Calendar my_Calendar;private int my_Year, my_Month, my_Day, my_Hour,my_Minute;

第34页:日期时间功能代码

设置日期和时间的设计与实现

详细功能实现部分:

public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);my_datePicker =(DatePicker)findViewById(R.id.datePicker);my_timePicker =(TimePicker)findViewById(R.id.timePicker);dateView = (TextView)findViewById(R.id.dateShow);timeView = (TextView)findViewById(R.id.timeShow);//获取当前的年、月、日、小时、分钟my_Calendar = Calendar.getInstance(Locale.CHINA);my_Year = my_Calendar.get(Calendar.YEAR);my_Month = my_Calendar.get(Calendar.MONTH);my_Day =my_Calendar.get(Calendar.DAY_OF_MONTH);my_Hour = my_Calendar.get(Calendar.HOUR_OF_DAY);my_Minute = my_Calendar.get(Calendar.MINUTE);// TimePicker支持24小时制my_timePicker.setIs24HourView(true);//初始化DatePicker组件,同时指定监听器my_datePicker.init(my_Year, my_Month, my_Day,newOnDateChangedListener(){@Overridepublic void onDateChanged(DatePicker view, intyear,int monthOfYear,int dayOfMonth){my_Year = year;my_Month = monthOfYear + 1;//因为1月在系统中的初始值为0,所以需要加1my_Day = dayOfMonth;//用TextView来显示设置好的日期dateView.setText("您设置的日期是:" +my_Year + "年" + my_Month+"月" + my_Day + "日");}});//为TimePicker指定监听器my_timePicker.setOnTimeChangedListener(newOnTimeChangedListener(){@Overridepublic void onTimeChanged(TimePicker view, inthourOfDay, int minute){my_Hour = hourOfDay;my_Minute = minute;//用TextView来显示设置好的时间timeView.setText("您设置的时间是:" +my_Hour + "时" + my_Minute + "分");}});}}

第35页:导航条章节目录

本章目录

  • 导航条的设计与实现
  • 用户界面基础
  • 友好登录界面的设计与实现
  • 注册界面的设计与实现
  • 图片浏览器的设计与实现
  • 设置日期与时间的设计与实现
  • 模拟文件下载进度条的设计与实现
  • 考试系统界面的设计与实现
  • 模拟PPS(网络电视)消息提醒的设计与实现
  • 本章小结
  • 项目实训

第36页:ListView三个关键元素

导航条的设计与实现

预备知识:

ListView组件在稍微复杂点的布局中都会用到,利用它可以让用户界面美观、有层次,该组件是android.widget.AbsListView的子类,既可以用来作为数据显示的容器,也可以作为界面的布局。在使用ListView显示内容时,包含3个关键元素。

  • (1)用来显示数据的ListView组件。ListView组件可以直接在布局文件中定义,也可以通过继承ListActivity类获得。
  • (2)用来显示的数据data。data是被映射的字符串、图片或基本组件。
  • (3)用来把数据映射到ListView上的适配器ListAdapter。根据列表的适配器类型,列表分为3种,ArrayAdapter、SimpleAdapter和SimpleCursorAdapter。

3个关键元素的关系如图3.11所示。ListView组件的常用属性见表3-6。

第37页:普通ListView使用步骤

导航条的设计与实现

预备知识

  • 1.普通ListView组件使用步骤如下。

(1)在要显示列表的界面布局文件中添加ListView组件,代码如下:

<ListViewandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:id="@+id/listview"/>

(2)定义数据适配器,前面已经介绍过,数据适配器有ArrayAdapter、SimpleAdapter和SimpleCursorAdapter3种类型。其中ArrayAdapter最简单,它只能展示一行文本信息;SimpleAdapter有最好的扩充性,可以自定义各种效果,在下面的自定义ListView组件中会详细介绍;SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,可以方便地将数据库的内容以列表的形式展示出来,它的用法将在第7章中介绍,本节不再详述。实现代码如下:ArrayAdapteradapter=newArrayAdapter(this,android.R.layout.simple_list_item_1,items);

ArrayAdapter有3个参数,第一个参数为Context,第二个参数为Android系统提供的常用布局风格(表3-7)或自定义的布局文件(将在“自定义ListView组件”中详细介绍),第三个参数为数组(即ListView列表中的内容,不能用int型数组)。

第38页:自定义ListView预备知识

导航条的设计与实现

预备知识

第39页:自定义列表项布局

导航条的设计与实现

预备知识

  • 2。自定义ListView组件

(1)在要显示列表的界面布局文件中添加ListView组件,代码与普通ListView组件一样。

(2)自定义显示列表项的布局文件。在有些应用程序中,列表行不只是显示一个文本信息,有的会在一行上显示姓名和电话号码,也有的会在一行上显示头像和姓名等,这些需求用普通ListView组件的使用方法就不能实现,对于这类需求,需要在项目文件夹的res/layout文件夹下新建一个布局文件person.xml,与普通布局文件的创建方法相同,代码如下:

<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android=http://schemas.android.com/apk/res/androidandroid:orientation="horizontal"android:layout_width="fill_parent"android:layout_height="fill_parent"><ImageViewandroid:id="@+id/icon"android:layout_width="48dip"android:layout_height="48dip"/><TextViewandroid:id="@+id/text"android:layout_gravity="center_vertical"android:layout_width="0dip"android:layout_weight="1"android:layout_height="wrap_content"/></LinearLayout>

上述代码表示在ListView组件的一行上,分别用一个ImageView组件和一个TextView组件显示头像和姓名。

第40页:SimpleAdapter适配器

导航条的设计与实现

  • (3)定义数据适配器。为了灵活使用自定义ListView组件,需要使用SimpleAdapter适配器。使用SimpleAdapter适配器需要分两步完成。

第一步:定义数据结构,添加数据。从ListView组件显示信息的本身来分析,纵向看,ListView就是一个List,横向看,ListView是一个包含键值对的Map,所以数据结构就是List

<Map<String,Object>>,添加数据的关键代码如下:List<HashMap<String,Object>>data=newArrayList<HashMap<String,Object>>();HashMap<String,Object>info=newHashMap<String,Object>();//将头像和姓名分别放入Map键值对中info.put("img",R.drawale.icon1);info.put("name","王庆林");data.add(info);

第二步:使用SimpleAdapter向ListView中填入数据。SimpleAdapter将一个List作为数据源,可以让ListView进行更加个性化的显示。它的构造方法格式如下:SimpleAdapter(Contextcontext,List

<?ExtendsMap<String,?>>data,intresource,String[]from,int[]to);参数说明:Context表示当前上下文;Data表示数据源;Resource表示自定义的布局文件资源;From表示定义ListView中的每一项数据索引,也就是Map中的键集合;To表示自定义布局文件中的资源ID集合,与From的参数要一一对应。代码如下:SimpleAdapteradapter=newSimpleAdapter(ListViewActivity.this,data,R.layout.person,newString[]{"img","name"},newint[]{R.id.icon,R.id.text});
  • (4)将适配器与ListView相关联,代码如下:

lvwSimple.setAdapter(adapter);

第41页:ListView单击监听

导航条的设计与实现

预备知识

  • 3.给ListView设置单击列表项监听事件lvwSimple.setOnItemClickListener(new OnItemClickListener(){

    @Overridepublic void onItemClick(AdapterView<?> parent, View view, intposition, long id){HashMap<String, String> info = data.get(position);String name = info.get(name);}});

第42页:导航条主界面布局

导航条的设计与实现

导航条界面设计

主界面布局如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><ListViewandroid:id="@+id/myList"android:layout_width="fill_parent"android:layout_height="wrap_content"android:dividerHeight="2px"android:layout_marginLeft="4px"/><!--距离左边4像素,android:dividerHeight="2px"表示选项间隔2像素--></LinearLayout>

第43页:Item选项布局文件

导航条的设计与实现

Item选项的布局:

<?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" ><ImageViewandroid:id="@+id/myImageView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="3px"android:layout_marginTop="3px" /><TextViewandroid:id="@+id/nameTextView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_marginLeft="50px"android:textSize="24sp" /></LinearLayout>

第44页:导航条功能实现

导航条的设计与实现

导航条的功能实现:

public class MainActivity extends Activity {private ListView listView;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);listView = (ListView)findViewById(R.id.myList);List<HashMap<String, Object>> list = new ArrayList<HashMap<String,Object>>();//定义List,list中存储的是HashMap类型的元素HashMap<String, Object> map1 = new HashMap<String, Object>();HashMap<String, Object> map2 = new HashMap<String, Object>();HashMap<String, Object> map3 = new HashMap<String, Object>();HashMap<String, Object> map4 = new HashMap<String, Object>();HashMap<String, Object> map5 = new HashMap<String, Object>();

第45页:HashMap数据填充

导航条的设计与实现//为每个HashMap添加具体的内容map1.put("picture", R.drawable.baidu);map1.put("name", "百度");map2.put("picture", R.drawable.sina);map2.put("name", "新浪");map3.put("picture", R.drawable.sohu);map3.put("name", "搜狐");map4.put("picture", R.drawable.tencent);map4.put("name", "腾讯");map5.put("picture", R.drawable.google);map5.put("name", "谷歌");//把每个map添加到list列表中list.add(map1);list.add(map2);list.add(map3);list.add(map4);list.add(map5);

第46页:SimpleAdapter声明

导航条的设计与实现SimpleAdapter adapter = new SimpleAdapter(this,list,R.layout.guidelist,new String[] { "picture", "name" },new int[] { R.id.myImageView, R.id.nameTextView });listView.setAdapter(adapter);//将SimpleAdapter绑定到ListView上listView.setOnItemClickListener(new myListener());//对ListView的item实现单击事件的监听}

第47页:列表项事件监听

导航条的设计与实现//事件监听部分:class myListener

implements OnItemClickListener {private Intent intent;@Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3){switch (arg2){case 0:intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http:// www.baidu.com"));startActivity(intent);break;case 1:intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http:// www.sina.com"));startActivity(intent);break;case 2:intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http:// www.sohu.com"));startActivity(intent);break;case 3:intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http:// www.qq.com"));startActivity(intent);break;case 4:intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http:// www.google.com.hk"));startActivity(intent);break;}}}}

第48页:Internet权限配置

导航条的设计与实现

由于本案例代码中实现了Internet连接,在单击了如图所示的“百度”导航条后,会出现如图3.13所示的效果,所以需要在配置文件AndroidManifest.xml中添加Internet访问权限,代码如下所示:

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

第49页:进度条章节目录

本章目录

  • 模拟文件下载进度条的设计与实现
  • 用户界面基础
  • 友好登录界面的设计与实现
  • 注册界面的设计与实现
  • 图片浏览器的设计与实现
  • 设置日期与时间的设计与实现
  • 导航条的设计与实现
  • 考试系统界面的设计与实现
  • 模拟PPS(网络电视)消息提醒的设计与实现
  • 本章小结
  • 项目实训

第50页:ProgressBar预备知识

模拟文件下载进度条的设计与实现

预备知识

  • 在Android系统中,ProgressBar(进度条)组件,可以向用户显示某个应用程序耗时操作完成的百分比,因此它需要动态地显示进度,从而避免因长时间执行某个耗时的操作,而让用户感觉程序失去了响应,从而提高用户界面的友好性。
  • 为了适应不同的应用环境,Android系统内置了多种不同风格的进度条,开发者可以在XML布局文件中通过Style属性来设置ProgressBar的风格,Style常用属性值及说明见表3-8。

第51页:ProgressBar属性表

模拟文件下载进度条的设计与实现

ProgressBar的常用属性及说明如表3-9

ProgressBar的常用属性的方法及说明如表3-10

第52页:下载进度条界面代码

模拟文件下载进度条的设计与实现

文件下载进度条的界面实现。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:id="@+id/linear1"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><TextViewandroid:id="@+id/sizeView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="文件大小:"android:textSize="20sp" /><EditTextandroid:id="@+id/inputEdit"android:layout_width="150dp"android:layout_height="wrap_content"android:layout_marginLeft="3dp"android:inputType="numberDecimal"android:textSize="20sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingLeft="10dp"android:text="MB"android:textSize="20sp" /></LinearLayout><LinearLayoutandroid:id="@+id/linear2"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:orientation="horizontal" ><ProgressBarandroid:id="@+id/progressBar1"style="?android:attr/progressBarStyleHorizontal"android:layout_width="255dp"android:layout_height="wrap_content"android:visibility="visible" /><TextViewandroid:id="@+id/persentView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingLeft="5dp"android:text="进度"android:textSize="20sp" /></LinearLayout><Buttonandroid:id="@+id/downBtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="下载"android:textSize="20sp" /></LinearLayout>

第53页:水平进度条说明

模拟文件下载进度条的设计与实现

本案例中运用的是水平进度条,可以用来显示刻度。EditText输入的数据表示要下载文件的大小,单击“下载”按钮后,每隔0.1秒水平进度条加1。

当单击“下载”按钮时,开始下载。代码中运用了线程来控制UI中的组件,通过Handler对象来传递信息。

第54页:进度条功能实现代码

模拟文件下载进度条的设计与实现

文件下载进度条详细功能实现代码如下:

public class MainActivity extends Activity {private ProgressBar pb;private EditText inputET;private Button downBtn;private TextView showView;private int progressValue = 0;private String s;private int size;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);pb = (ProgressBar)findViewById(R.id.progressBar1);inputET = (EditText)findViewById(R.id.inputEdit);downBtn = (Button)findViewById(R.id.downBtn);showView = (TextView)findViewById(R.id.persentView);downBtn.setOnClickListener(new Listener());}

第55页:下载按钮监听代码

模拟文件下载进度条的设计与实现class Listener implementsOnClickListener{

@Overridepublic voidonClick(View v){s =inputET.getText().toString();//获取文本框输入的字符串size =Integer.parseInt(s);//将字符串转换成整数pb.setMax(size);//设置进度条的最大值Threadthread= new Thread(myRun);thread.start(); 

第56页:Handler对象创建

模拟文件下载进度条的设计与实现//创建Handler对象Handler handler =

new Handler(new Callback(){// public boolean handleMessage(Message arg0)是Callback的方法,// Callback是Handler这个类的一个内部接口,//而boolean handleMessage()是这个接口的函数@Overridepublic boolean handleMessage(Message msg){pb.setProgress(msg.arg1);//接收另一线程的Message,参数arg1代表了进度showView.setText((int)(msg.arg1 * 1.0 / size * 100)+ "%");//设置显示的进度,只显示整数pb.setSecondaryProgress(msg.arg1 + 10);//设置第二进度值return false;}});

第57页:考试系统章节目录

本章目录

  • 考试系统界面的设计与实现
  • 用户界面基础
  • 友好登录界面的设计与实现
  • 注册界面的设计与实现
  • 图片浏览器的设计与实现
  • 设置日期与时间的设计与实现
  • 导航条的设计与实现
  • 模拟文件下载进度条的设计与实现
  • 模拟PPS(网络电视)消息提醒的设计与实现
  • 本章小结
  • 项目实训

第58页:TabHost预备知识

考试系统界面的设计与实现

预备知识

  • TabHost是整个Tab的容器,包括两部分:TabWidget和FrameLayout。TabWidget就是每个Tab的标签,是可供用户选择的标签集合;FrameLayout是显示内容的帧布局,FrameLayout的内容将在第4章详细介绍,每个Tab都对应自己的布局。TabHost提供了如下两个方法来创建选项卡、添加选项卡。

(1)newTabSpec(String tag):创建一个以tag为标识的选项卡。

(2)addTab(TabHost.TabSpec tabSpec):向TabHost中添加一个tabSpec选项卡。

  • TabHost的实现有两种方式。

第59页:TabActivity实现步骤

考试系统界面的设计与实现

1.Activity继承TabActivity,实现步骤如下。

  • (1)因为TabActivity类默认包含了一个TabHost组件,所以直接调用getTabHost()方法获取TabHost对象。
  • (2)调用LayoutInflater.from(this).inflate(R.layout.tabhost_layout,tabhost.getTabContentView(), true)方法,将Tab页的布局转换为Tab标签页可以使用的View对象。inflate()方法的第一个参数表示要使用的布局文件资源ID;第二个参数表示持有选项卡的内容,获取FrameLayout;第三个参数表示解析的XML文件为根视图View。
  • (3)调用addTab(tabHost.newTabSpec(Stringtag).setIndicator(CharSequence label, Drawable icon).setContent(intviewId))方法,添加Tab页。setIndicator()方法的第一个参数表示Tab的标题;第二个参数表示Tab的图标;setContent()方法用于设定Tab页所关联的布局文件资源ID。

2.Activity不继承TabActivity,实现步骤

  • (1)在布局文件中定义TabHost组件,TabWidget的id必须是@android:id/tabs,FrameLayout的id必须是@android:id/tabcontent。
  • (2)使用TabHost tabHost=(TabHost)findViewById(R.id.tabhost)语句获得TabHost对象,并通过tabHost.setup()方法加载启动tabHost。
  • (3)与继承TabActivity的步骤一样。

第60页:考试系统整体布局

考试系统界面的设计与实现

本案例中采用的是Activity不继承TabActivity的方式,在布局文件中定义了TabHost、TabWidget、FrameLayout,并把需要显示的单选题、多选题、判断题和填空题的4个标签页放在了布局文件中

整体布局代码如右所示:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><TabHostandroid:id="@+id/tabhost"android:layout_width="fill_parent"android:layout_height="wrap_content" ><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="vertical" ><TabWidgetandroid:id="@android:id/tabs"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" /><FrameLayoutandroid:id="@android:id/tabcontent"android:layout_width="fill_parent"android:layout_height="fill_parent" >...... 

第61页:填空题页面布局

考试系统界面的设计与实现

由于几个Tab页的的布局类似,此处只给出其中填空题页面的布局。

<!--填空题布局--><LinearLayoutandroid:id="@+id/fill"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="vertical" ><TextViewandroid:id="@+id/fanswerValue"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="1.一幅分辨率为512×512的彩色图像,其R、G、B三个分量分别用8个二进位表示,则未进行压缩时该图像的数据量是多少kB?"android:textSize="18sp" /><EditTextandroid:id="@+id/fillValue"android:layout_width="fill_parent"android:layout_height="wrap_content"android:hint="请输入答案"android:textSize="18sp" /></LinearLayout>

第62页:Tab页图标与标题代码

考试系统界面的设计与实现

详细的设计tab页图标、标题的功能设计代码如下:

public class MainActivity extends Activity {public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);TabHost tabHost = (TabHost)findViewById(R.id.tabhost);//获得TabHost对象tabHost.setup();//通过setup()方法加载启动TabHosttabHost.addTab(tabHost.newTabSpec("tab01").setIndicator(("单选题"),getResources().getDrawable(R.drawable.single)).setContent(R.id.singleChoice));tabHost.addTab(tabHost.newTabSpec("tab02").setIndicator(("多选题"),getResources().getDrawable(R.drawable.multi)).setContent(R.id.multiChoice));tabHost.addTab(tabHost.newTabSpec("tab03").setIndicator(("填空题"),getResources().getDrawable(R.drawable.fillbank)).setContent(R.id.fill));tabHost.addTab(tabHost.newTabSpec("tab04").setIndicator(("判断题"),getResources().getDrawable(R.drawable.judge)).setContent(R.id.judge));}}

第63页:消息提醒章节目录

本章目录

  • 模拟PPS(网络电视)消息提醒的设计与实现
  • 用户界面基础
  • 友好登录界面的设计与实现
  • 注册界面的设计与实现
  • 图片浏览器的设计与实现
  • 设置日期与时间的设计与实现
  • 导航条的设计与实现
  • 模拟文件下载进度条的设计与实现
  • 考试系统界面的设计与实现
  • 本章小结
  • 项目实训

第64页:Notification组件说明

模拟PPS(网络电视)消息提醒的设计与实现

Notification组件一般用在电话、短信、闹铃铃声中。例如,手机网易新闻客户端、QQ空间客户端,以及短信、未接电话提示等应用有消息需要提示用户时,在手机的状态栏上就会出现一个小图标,提示用户处理这个信息,此时从上方滑动状态栏就可以展开并处理这类信息。

使用Notification一般有3个步骤。

  • (1)获得系统级的服务NotificationManage,调用Context.getSystemService(NOTIFICATION_SERVICE)方法即可返回NotificationManager实例。
  • (2)实例化Notification,并设置其属性。

实例化Notification可用它的构造方法,格式如下:public Notification(inticon,CharSequencetickerText, long when),第一个参数是通知的图标;第二个参数是标题信息;第三个参数是系统时间。Notification常用属性及说明见表3-11。

  • (3)通过NotificationManager发送通知。

使用NotificationManager的notify()发送通知,notify()的格式如下:notify(intid,Notificationnotification)。

第一个参数表示通知唯一的标识;第二个参数是Notification对象。当然也可以使用NotificationManager的cancel(intid)方法取消通知,参数同notify()方法。

Notification的defaults属性常用属性值如表3-12

Notification的flags属性常用属性值如表3-13

第65页:消息提醒界面代码

模拟PPS(网络电视)消息提醒的设计与实现

因为本案例中界面设计比较简单,只运用了两个Button组件、一个用于发送通知,一个用于取消通知。详细设计代码:

private Button sendBtn,cancleBtn;private NotificationManager mNotificationManager; 

第66页:消息提醒按钮监听

模拟PPS(网络电视)消息提醒的设计与实现

按钮事件监听实现部分:sendBtn

.setOnClickListener(new OnClickListener(){//发送通知按钮单击//事件监听@Overridepublic void onClick(View v){mNotificationManager.notify(0,notification);//通过NotificationManager//发送Notification}});cancleBtn.setOnClickListener(new OnClickListener(){//取消通知按钮单击//事件监听@Overridepublic void onClick(View v){mNotificationManager.cancel(0);//通过NotificationManager取消Notification}});

第67页:小结章节目录

本章目录

  • 本章小结
  • 用户界面基础
  • 友好登录界面的设计与实现
  • 注册界面的设计与实现
  • 图片浏览器的设计与实现
  • 设置日期与时间的设计与实现
  • 导航条的设计与实现
  • 模拟文件下载进度条的设计与实现
  • 考试系统界面的设计与实现
  • 模拟PPS(网络电视)消息提醒的设计与实现
  • 项目实训

第68页:本章小结

本章小结

本章结合案例介绍了Android中常用的基本组件:TextView、EditText、Button、ImageButton、RadioButton、CheckBox、DatePicker、TimePicker、ImageView、ListView、TabHost等的使用方法。读者通过对基本组件的常用属性、常用方法的学习,可以开发出简单的Android项目,同时也为后续的Android应用开发打下良好的基础。

第69页:实训章节目录

本章目录

  • 项目实训
  • 用户界面基础
  • 友好登录界面的设计与实现
  • 注册界面的设计与实现
  • 图片浏览器的设计与实现
  • 设置日期与时间的设计与实现
  • 导航条的设计与实现
  • 模拟文件下载进度条的设计与实现
  • 考试系统界面的设计与实现
  • 本章小结
  • 模拟PPS(网络电视)消息提醒的设计与实现

第70页:项目实训

项目实训

项目一

项目名:简单ListView。

功能描述:用ListView组件和ArrayAdapterr适配器完成如图3.19所示的星期列表

项目二

项目名:通讯录。

功能描述:用ListView组件、ImageView组件、TextView组件、Button组件和SimpleAdapter适配器完成如图3.20所示的通讯录。

项目三

项目名:考试系统。

功能描述:用Activity继承TabActivity实现3.8节的考试系统。

第71页:第三章结束致谢页

The end,thank you!