第 1 章 Android 应用初体验
请参考教材,全面理解和完成本章节内容... ...
本章将通过设计首个应用名为GeoQuiz, 介绍编写Android应用需掌握的一些基概念和设计方法。
移动系统的的应用也叫App,本章的App能测试用户的地理知识。图1-1显示了用户点击“对”按钮的结果。
图1-1 正确答案应该是台湾,而不是海南岛
1.1 Android应用基础
GeoQuiz应用由一个activity(活动)和一个布局(layout)组成。
其中,Activity中文可以翻译为活动或者活动界面。
- 从用户角度来看, Activity就是包含用户界面的一个大组件,主要用于和用户进行交互。一个应用程序中可以包含1个或多个Activity。
- 从程序设计的角度来看,Activity是Android SDK中Activity类的一个具体实例,负责管理用户与信息屏的交互。Android应用程序的功能是通过编写一个个Activity子类来实现的。简单的应用可能只需一个子类,而复杂的应用则会有多个子类。
本章的GeoQuiz应用很简单,因此它只有一个Activity名为 QuizActivity (继承自 Activity 的子类)。QuizActivity 负责管理 图1-1所示的用户界面。
布局(layout)定义了一系列用户界面对象以及它们显示在屏幕上的位置。组成布局的定义保存在XML文件中。每个定义用来创建屏幕上的一个对象,如按钮或文本信息。
GeoQuiz应用包含一个名为activity_quiz.xml的布局文件,该文件中的XML标签定义了图1-1所示的用户界面。
通常,一个Activity对应一个layout(布局),如QuizActivity的布局是activity_quiz.xml文件。在本章中,QuizActivity管理着activity_quiz.xml文件定义的用户界面,它们之间的关系如图1-2所示。
图1-2 Activity、布局文件和用户界面关系图
学习了这些基本概念后,我们来创建本书第一个应用。
1.2 创建 Android 项目
首先,在根目录下建一个目录,用来保存项目文件。英文命名,比如F:\Mywork\AS\ch1\,代表第一章的工程目录。
接下来,启动Android Studio 程序,选择右侧 Start a new Android Studio project菜单项;此时,Android Studio打开一个向导来帮助我们来创建一个新的项目。
在第一个向导窗口中,在应用名称(Application Name)处输入GeoQuiz,在公司域名(Company Domain)处输入jet.com(其中jet是我的英文名),如图1-3所示。此时包名处(Package Name)会自动更新为com.jet.geoquiz。
在项目位置处(Project location)选择一个合适位置,不要有中文路径,如F:\Mywork\AS\ch1\,其中AS 代表Android 学习、ch1代表第一章。
图1-3 创建新应用
注意,以上输入的包名遵循了“DNS反转”约定,亦即将个人或公司的域名反转后,在尾部附加上应用名称。遵循此约定可以保证包名的唯一性,这样,同一设备和Google Play商店的各类应用就可以区分开来。
- Application Name此处填写想呈现给用户的应用名称,此处我们使用“GeoQuiz”。
- Company domain 包名限定符,Android Studio会将这个限定符应用于每个新建的Android项目。
- Package Name是应用的包命名空间(同Java的包的概念),我们也可以独立地编辑该包名。
- Project location 存放项目的目录。
现在单击Next按钮。
接下来的四个选项用来配置应用如何与不同版本的Android设备适配。GeoQuiz应用只需使用默认设置,其他选项忽略。
Android开发工具每年会更新多次,因此当前的向导画面看起来可能会与图1-4略有不同。这一般不是问题,工具更新后,向导画面的配置选项应该不会有太大差别。
图1-4 选择App运行的Android版本
现在单击Next按钮。
图1-5所示的窗口询问想要创建的activity类型。选择Blank Activity。
图1-5 创建一个Blank activity
单击Next按钮继续
在应用向导的最后一个窗口,命名activity子类为QuizActivity
,如图1-6所示:
图1-6 配置建的activity
最后,单击Finish按钮。Android Studio完成创建并打开新的项目。(有时还是漫长的等待…)
1.3 Android Studio 工作区导航
如图1-7所示(可放大),第一次运行 Android Studio时工作区窗口会打开多个视图,熟悉后,可以按需开关某些视图。
图1-7 调整安排工作区窗口
整个工作区窗口分为不同的区域,这里统称为视图。最左边视图1是项目导航(Project)视图,通过它可以管理所有项目相关的文件。项目导航视图里的目录结构可以设置为“Android”或者“Project”类型,点击图1-7左上角红框可完成设置。我们采用“Android”结构显示项目文件目录;
中间部分视图2是UI设计区和代码编辑区视图。Android Studio默认在中间部分显示UI设计区 (打开 activity_quiz.xml文件)。
在工作区的底部视图3还有一些其他视图,显示一些编译信息、警告或建议信息、代码调试信息等。
工作区的每个视图都以分组面板(tab group)形式显示,可切换不同分组显示不同视图。
1.4 用户界面设计
通常,Android Studio向导会帮我们生成一个布局文件activity_quiz.xml。布局文件统一放置在\app\res\layout\目录, 所有layout文件都放在这里。
如图1-7所示,在中间部分已默认打开activity_quiz.xml布局文件,并在图形布局工具Design里显示了预览界面。虽然图形化布局工具非常好用,但为更好地理解布局的内部原理,我们还是先学习如何使用XML代码来定义布局。
在中间部分视图2的底部选择标为Text的标签页,从布局界面Design切换到XML代码界面Text。
注意,activity_quiz.xml文件定义了默认的activity布局,但基本布局经常改变。一个典型的“Hello World”布局如代码清单1-1所示。你可以参照代码清单1-1的内容,修改“activity_quiz.xml”布局文件。其中粗体内容是需要你输入的,非粗体内容是之前代码。(注意,Android Stuido 1.4 Beta 3会生成content_quiz.xml文件,请其内容复制到activity_quiz.xml,注释掉 <include layout="@layout/content_quiz"/> )。
代码清单1-1 基本activity布局(activity_quiz.xml)
应用activity的布局默认定义了两个组件(widget):RelativeLayout
和TextView
。
组件是组成用户界面的构造模块。组件可以显示文字或图像、与用户交互,甚至是布置屏幕上的其他组件。按钮、文本输入控件和选择框等都是组件。
Android SDK内置了多种组件,通过配置各种组件可获得所需的用户界面及行为。每一个组件是View
类或其子类(如TextView
或Button
)的一个具体实例。
图1-8展示了代码清单1-1中定义的RelativeLayout
和TextView
是如何在屏幕上显示的。
图1-8 显示在屏幕上的默认组件
不过,图1-8所示的“Hello World”布局太简单,并不是我们需要的。
GeoQuiz
应用的用户界面需要下列五个组件:
- 一个垂直
LinearLayout
组件; - 一个
TextView
组件; - 一个水平
LinearLayout
组件; - 两个
Button
组件。
图1-9展示了以上组件是如何构成QuizActivity
用户界面的。
图1-9 布置并显示在屏幕上的组件
现在,我们重新定义在activity_quiz.xml文件中定义QuizActivity
应用的用户界面:
由于修改内容多,请按照代码清单1-2所示,输入新代码。
代码清单1-2 在XML文件(activity_quiz.xml)中定义组件
注:就算不能完全理解这些代码也没关系,你会在后续的学习中弄明白的。需要特别注意的是,开发工具无法完全校验布局XML内容,请避免输入或拼写错误。
根据所使用的工具版本不同,有三行以android:text开头的代码会产生错误信息(红色)。暂时忽略它们,稍后会处理。
将XML文件与图1-9所示的用户界面进行对照,可以看出组件与XML元素一一对应。元素的名称就是组件的类型。
各元素均有一组XML属性。属性可以看作是如何配置组件的指令。
为便于理解元素与属性的工作原理,接下来我们将以层次等级的视角来研究布局.
1.4.1 视图层级结构
组件之间有上下级关系(包含和被包含的关系),也有平级的关系。可以用图来描述这种关系,即视图层级结构图。
请参考教材, 进一步理解本节内容...
1.4.2 组件属性
请参考教材,理解和完成本节内容... ...。
1.4.3 添加应用的字符串资源
每个项目都包含一个名为strings.xml的默认字符串文件。
在项目导航视图中,找到res\values目录,然后打开strings.xml文件。可以看到,项目模版已经默认添加了一些字符串资源。删除不需要的hello_world部分,添加GeoQuiz应用布局所需要的新的字符串,如代码清单1-3所示。
代码清单1-3 添加字符串资源(strings.xml)
现在,在GeoQuiz项目的任何XML文件中,只要引用到@string/false_button
,应用运行时,就会得到文本“错”。
1.4.4 预览界面布局
在编辑区底部选择图形布局标签Design页进行界面布局预览,如图1-11所示。
图1-11 在图形布局工具中预览界面布局(activity_quiz.xml)
1.5 从布局 XML 到视图对象
上一节,GeoQuiz应用的用户界面设计已经做好,但这仅仅是个静态的界面,用户还无法通过界面与我们的程序交互。如何处理这个问题?
想要实现交互,程序必须要知道用户在用户界面上做了那些动作,然后程序才能作出相应的反应(也叫响应用户事件),如何实现?
- 第一,程序要知道用户界面上有哪些组件(界面元素),然后将它们分别绑定给对应的类对象。例如,将用户界面上按钮组件与一个Button类对象绑定,即将布局里的静态的“界面元素”变成动态的视图对象。
- 第二,程序要时刻监听视图对象,如果用户与这些对象进行交互(如点击按钮),程序要做出反应。(在GeoQuiz应用中,程序要做出的反应就是“告诉用户的选择是否正确“)
本节先解决第一个问题:程序要知道用户界面上有哪些组件对象,即将布局里的“界面元素”内容转换为视图对象。
那么它是如何转换为视图对象的?答案就在 QuizActivity
类中。
activity_quiz.xml 用来定义用户界面的布局文件,文件中每个 XML元素对应一个“界面元素”。我们可以利用QuizActivity类把每个“界面元素”赋给(绑定到)对应的视图对象.
在创建 GeoQuiz 项目的同时,也创建了一个名为 QuizActivity
类,它是 AppCompatActivity
子类。QuizActivity
类文件存放在项目的\app\java\包目录下。
在项目导航视图中,依次展开\app\java\com.jet.geoquiz\, 打开QuizActivity.java文件。逐行查看其中的代码。
代码清单1-4 QuizActivity
的默认类文件(QuizActivity.java)
注意:教材中Activity
子类的父类都是Activity,为了更好的兼容,本文全部为AppCompatActivity ,如下所示:
原为:public class QuizActivity extends Activity{
改为:publicclassQuizActivityextendsAppCompatActivity{
在QuizActivity
类中,重写了(Override)onCreate(Bundle)
方法。这样QuizActivity
类的实例创建后,onCreate(Bundle)
方法会被自动调用。
QuizActivity
类的实例需要获取并管理属于自己的用户界面。可通过调用其父类的方法setContentView,获取布局文件资源,即用户界面,方法原型如下:
public void setContentView(int layoutResID)
通过传入布局资源的ID参数,该方法生成指定布局的视图并将其放置在屏幕上。布局视图生成后,布局文件包含的组件也随之以各自的属性定义完成实例化。
资源与资源ID
请参考教材…。
代码清单1-6 为按钮添加资源ID(activity_quiz.xml)
1.6 组件的实际应用
请参考教材…
既然按钮有了资源ID,就可以在QuizActivity
中直接获取它们。首先,在QuizActivity.java文件中增加两个成员变量。如代码清单1-8所示代码:
代码清单1-8 添加成员变量(QuizActivity.java)
1.6.1 使用Alt+Enter快捷键
使用Alt+Enter快捷键,可以帮助我们快速更正错误;
当你在错误代码附近按下组合键Alt+Enter时, Android Studio会依据代码自动帮你修正错误。包括,帮你决定应该导入哪些Java或Android SDK类包、修正简单语法错误。
对于上面的错误(Button 变红色)如果还没有解决,按下组合键Alt+Enter红色错误提示应该就会消失了。(如错误提示仍在,请检查代码是否拼写错误)
接下来,我们通过以下两个步骤,就能使用布局文件里的两个按钮:
- 引用组件:引用生成的视图对象;
- 设置监听器:为对象设置监听器,以响应用户操作。
1.6.2 引用组件
在activity中,可通过以下Activity
类
提供的findViewById方法引用已生成的组件:
public View findViewById(int id)
该方法接受组件的资源ID作为参数,返回一个视图对象。
在QuizActivity.java文件中,使用按钮的资源ID获取生成的对象后,赋值给对应的成员变量,如代码清单1-9所示。注意,赋值前,必须先将返回的View
转型(cast)为Button
。
代码清单1-9 引用组件(QuizActivity.java)
文件保存后,如果有错误提示,检查一下activity_quiz.xml和strings.xml文件,看看里面是不是有错误. 修改错误后重新保存所有文件。
1.6.3 设置监听器
请参考教材,理解和完成本节内容... ...。
代码清单1-10 为True按钮设置监听器(QuizActivity.java)
代码清单1-11 为False按钮设置监听器(QuizActivity.java)
创建提示消息
接下来要实现的就是,分别单击两个按钮,弹出我们称为toast的提示消息。Android的toast指用来通知用户的简短弹出消息,但无需用户输入或做出任何操作。这里,我们要做的就是使用toast来告知用户其答案正确与否,如图1-12所示:
图1-12 toast反馈消息提示
首先回到strings.xml文件,如代码清单1-12所示,为toast添加消息显示用的字符串资源。
代码清单1-12 增加toast字符串(strings.xml)
通过调用来自Toast
类的以下方法,可创建一个toast:
public static Toast makeText(Context context, int resId, int duration)
该方法的Context
参数通常是Activity
的一个实例(Activity
本身就是Context
的子类)。第二个参数是toast待显示字符串消息的资源ID。Toast
类必须利用context
才能找到并使用字符串的资源ID。第三个参数通常是两个Toast
常量中的一个,用来指定toast消息显示的持续时间。
创建Toast后,可通过调用Toast.show()
方法使toast消息显示在屏幕上。
在QuizActivity
代码里,分别对两个按钮的监听器调用makeText()
方法,如代码清单1-13所示。在添加makeText()
时,可利用Android Studio的代码自动补全功能,让代码输入工作更加轻松。
代码清单1-13 创建提示消息(QuizActivity.java)
1.7 使用模拟器运行应用
要运行Android应用,需使用硬件设备或者虚拟设备(virtual device)。包含在开发工具中的Android设备模拟器可提供多种虚拟设备。(也可以使用海马玩模拟器 Droid4X等虚拟机)
要想创建Android虚拟设备(AVD),在Android Studio中,选择Tools->Android->AVD Manager菜单项,当AVD管理器窗口弹出时,点击窗口左下的Create Virtual Device按钮。
在随后弹出的对话框中,可以看到有很多配置虚拟设备的选项。按照 一系列图1-13所示进行配置。
图1-13-1 创建新的AVD
接下来,选择要模拟的手机(尽量选择低版本手机,速度快),建议选择Nexus S,如下图:
图1-13-2 选择要模拟的手机(Select Hardware)
接下来,选择一个系统镜像(Android版本和虚拟机CPU),Level17 ,x86,如下图:
图1-13-3 选择要模拟的手机(Select Hardware)
最后,给新建的AVD命名、设置显示比例等,默认就好,如下图:
图1-13-4 AVD命名、设置显示比例等
AVD创建成功后,我们用它运行GeoQuiz应用:
- 首先,选择Tools->Android->AVD Manager菜单项,运行之前新建的虚拟机(有点慢)
- 然后,在菜单Run->Edit Configurations 里选择GeoQuiz
- 最后,选择Run->Run ‘GeoQuiz’, 运行GeoQuiz应用。
Android会列表让你选择当前的虚拟机或实体机设备如图1-14,然后安装应用包(APK)并运行应用。
图1-14 AVD命名、设置显示比例等
启动虚拟机可能比较耗时,请耐心等待。设备启动完成,应用运行后,就可以在应用界面点击按钮,让toast告诉我们答案。(注意,如果应用启动运行后,我们凑巧不在电脑旁,回来时,就可能需要解锁AVD。如同一台真实设备,AVD闲置一定时间会自动锁上。)
如何你没有实体机,建议保持模拟器一直运行,这样就不必在反复运行调试应用时,痛苦地等待AVD启动了。单击回退按钮(即AVD模拟器上的U型箭头按钮)可以停止应用。需要调试变更时,再通过Android Studio重新运行应用。
虽然模拟器非常有用,但在真实设备上测试应用能够获得更准确的结果。在第2章中,我们将在真实硬件设备上运行GeoQuiz应用,并且为GeoQuiz应用添加更多地理知识问题,以供用户回答。