Android开发权威指南(第二版)
上QQ阅读APP看书,第一时间看更新

5.1 声明和使用Activity

本节将回顾一下Activity的基本用法,并且详细介绍了Activity的生命周期。深入理解Activity的创建和销毁的过程对于灵活使用Activity至关重要。除此之外,最新版的ADT为平板电脑提供了创建Android工程的模板,本节会介绍一下这个模板的使用方法。

5.1.1 Activity的基本用法

源代码目录:src/ch05/MobileActivity

本节会从Activity的创建、初始化和声明3个方面介绍Activity的基本使用方法。

在第3章的例子中已经使用过一次Activity。这个Activity是在建立Android工程时自动创建的一个窗口类。如果要向Android工程中增加新的Activity,可以使用下面两种方法。

创建Activity的模板。

创建一个从android.app.Activity继承的Java类。

如果使用创建Activity的模板,可以选中Android工程,在右键菜单中单击“New”>“Other”菜单项,这时会显示“New”对话框(如图5-1所示),选择“Android”>“Android Activity”节点。然后单击“Next”按钮进入下一界面。在这一界面通常保持默认值(BlankActivity)即可,BlankActivity表示创建一个空的窗口。除了BlankActivity之外,ADT还提供了其他的窗口模板,例如,FullscreenActivity生成一个全屏的窗口;LoginActivity生成一个用于登录的窗口,这些窗口模板只是多生成一些标准的代码,读者可根据自己的需要选择窗口模板。

实际上到这里已经可以单击“Finish”按钮创建窗口类了,不过创建的窗口类名是MainActivity,为了修改窗口类名,还需要单击“Next”按钮进入下一个界面,在“Activity Name”文本框中输入新的窗口类名,然后单击“Finish”按钮创建窗口类。

在默认情况下,使用Activity模板建立的窗口类会在Android工程中的如下目录和文件中添加相应的内容。

src:添加窗口类文件(java源文件)。

res/layout:添加窗口的默认布局文件。

res/menu:添加窗口的默认选项菜单文件。

res/values/strings.xml:添加一个字符串资源,用于窗口标题的文本。

AndroidManifest.xml:声明窗口类。

如果读者不想让Activity模板自动生成上述5项中的全部或部分内容,可以在“New”对话框中如图5-1所示的最后一个设置页面中取消某些选项的选中状态,这样ADT就不会自动生成相应的内容了。

创建Activity的模板不仅可以创建空窗口,还可以创建4种带Tab的窗口(默认3个Tab)。从图5-1所示的设置页回到上一个设置页,就会看到如图5-2的设置页面(在这个页面也可以修改窗口类名称、布局文件名等信息)。

 

▲图5-1 创建Activity时自动生成的内容

 

▲图5-2 创建Tab风格的Activity

在“Navigation Type”列表中会看到如下4种Tab风格的窗口。

Tabs:传统的Tab窗口。只能单击窗口上方的按钮切换Tab。

Tabs+Swipe:包含Tabs的风格,但也可以通过左右滑动切换Tab。

Swipe Views+Title Strip:只有通过左右滑动才能切换Tab。窗口顶端的风格也有所不同。

Dropdown:上面用于切换Tab的按钮变成了下拉菜单形式。不能通过左右滑动切换Tab。

从前面描述的4种Tab风格的窗口来看,只有Tabs+Swipe和Swipe View+Title Strip支持通过左右滑动的方式切换Tab。ADT会在这4种Tab风格的窗口对应的类中生成大量的代码,读者可以根据需要修改这些代码以符合自己的要求。图5-3、图5-4和图5-5是这4种窗口的效果图外框不属于界面效果,只是为了更好地突出窗口,否则界面底色会和书的空白处的颜色相近,无法看清界面的轮廓。,其中前两种窗口的风格完全一样,只是后者可以通过左右滑动的方式切换Tab。

 

▲图5-3 Tabs和Tabs+Swipe风格的窗口

如果想通过手工创建窗口类,首先需要创建一个普通的Java类,该类必须从android.app.Activity或其子类继承。然后至少要在res/layout目录中创建一个布局文件,并在AndroidManifest.xml文件中声明窗口类。

布局文件是为了在窗口上放置各种控件,假设建立的布局文件的文件名为myactivity.xml,在编译Android工程时会在R.layout类中生成一个名为myactivity的int类型变量。通常需要在窗口类的onCreate方法中使用setContentView方法将myactivity.xml布局文件中的控件显示在窗口上,代码如下:

public void onCreate(Bundle savedInstanceState)

{

  super.onCreate(savedInstanceState);

  // 将布局文件中的控件显示在窗口上

  setContentView(R.layout.myactivity);

}

 

 

▲图5-4 Swipe Views+Title Strip风格的窗口

 

▲图5-5 Dropdown风格的窗口

当然,我们还可以通过其他方式在窗口上显示控件,甚至是动态添加和删除控件,这一部分的内容会在讨论控件时详细介绍。

在使用模板创建Activity时会在AndroidManifest.xml文件中自动添加声明Activity的代码,例如,创建TabActivity时添加的声明代码如下:

<activity

  android:name=".TabActivity"

  android:label="@string/title_activity_tab" >

  <intent-filter>

      <action android:name="android.intent.action.MAIN" />

      <category android:name="android.intent.category.LAUNCHER" />

  </intent-filter>

</activity>

由于模板的原因,自动添加的声明会加入<intent-filter>标签,而且Action和CategoryAction和Category可以暂且理解为将一个Activity与一组字符串绑定。系统通过这组字符串可以找到一个或多个与这些字符串绑定的Activity。本章后面的部分会详细介绍Action和Category以及相关技术的用法。分别是android.intent.action.MAIN和android.intent.category.LAUNCHER。这是系统用于调用第一个显示的Activity的Action和Category。这个Action和Category可以在多个Activity中使用,如果在一个应用程序中声明了多个使用该Action和Category的窗口,系统会在程序列表中生成多个程序图标,每个图标对应某一个使用android.intent.action.MAIN和android.intent.category.LAUNCHER的窗口。当单击某个图标后就会显示与其对应的窗口。当然,程序启动时还是显示第一个使用android.intent.action.MAIN和android.intent.category.LAUNCHER的窗口。

如果声明普通的Activity,就没必要非得加<intent-filter>标签了,最简单的Activity声明方式只需要指定Activity的类名即可,代码如下:

<activityandroid:name=".TabActivity"/>

如果想让Activity的标题显示一个友好的名称,可以通过<activity>标签的android:label属性设置Activity的标题文本。

显示窗口需要通过Intent对象指定Activity类的class,并使用startActivity方法显示Activity,代码如下:

Intent intent = new Intent(this, TabActivity.class);

startActivity(intent);

5.1.2 同时适合手机和平板电脑的窗口风格

源代码目录:src/ch05/MobilePadActivity

自从平板电脑开始兴起以后,关于屏幕适配的问题就更加严重了。平板电脑是从Apple的iPad开始才被大众所接受的。由于在iPad之前已经有了iPhone,所以一直以来让IOS程序员引以自豪的UI设计迎来了第一次屏幕适配问题随着Apple用乔布斯留下的“擀面杖”将iPhone 5变长之后,将迎来第2次屏幕适配问题,也许还会有第3次……。苹果给出的方案是单独为iPhone和iPad设计两个不同的窗口。而Android可能要面临比iPhone和iPad更严重的屏幕适配问题毕竟到目前为止iPhone、iPhone 5和iPad只有3种屏幕支持,就是Apple推出了7英寸平板,也只不过才多了1种屏幕尺寸。,本来Android手机本身的屏幕适配问题就很令人头痛,这下又多出来个Android平板电脑。需要屏幕适配的机型就算不多出一倍,多出的数目也相当可观。

在这里先不谈Android手机本身的适配问题,只考虑Android手机和Android平板电脑的屏幕布局,因为这个问题更突出。由于Android手机和Android平板电脑的屏幕分辨率和屏幕大小往往差很多,所以一般不能使用像适配不同Android手机屏幕一样使用与屏幕分辨率无关的长度单位进行设置。下面我们来看一个例子。图5-6是在腾讯视频HDHD(high-definition)版,专门用于平板电脑的支持大分辨率的应用程序。版的截图。通过单击左侧视频种类的列表,会在右侧显示当前视频种类中的视频列表,但这种显示风格就不适合在手机上使用。因为手机屏幕尺寸比较小,如果按这种显示风格,或者字体和图像会显示得很小,或者需要上下或垂直的滚动,用户体验会很差。

 

▲图5-6 腾讯视频HD版

通常像腾讯视频这种界面在Android手机上需要分两个界面来显示。第一个界面显示视频种类列表,如图5-7所示。单击某一种类的视频后,应该另外弹出一个当前种类的视频列表,如图5-8所示。

像腾讯视频这种在平板电脑和手机上显示不同风格界面的效果从技术角度完全可以实现,而且可以将这两种风格的界面放到一个apk文件中,并不需要为手机和平板电脑分别做一个apk文件。但实现这种效果需要编写较多的代码,比较麻烦。不过最新的ADT为我们提供了这种界面风格的模板,只需要在创建Activity时选择该模板即可。

使用同时适应手机和平板电脑屏幕的窗口模板需要在“New”对话框中选择窗口模板时选中“MasterDetailFlow”(默认是BlankActivity),如图5-9所示。其他的操作和使用“BlankActivity”模板类似。

 

▲图5-7 显示视频种类(腾讯视频手机版)

 

▲图5-8 显示某一种类的视频列表(腾讯视频手机版)

使用MasterDetailFlow模板创建窗口类后,会自动生成很多源代码和资源文件,如图5-10所示。

 

▲图5-9 选择MasterDetailFlow模板

 

▲图5-10 使用MasterDetailFlow模板创建Activity后的Android工程结构

MasterDetailFlow模板使用了一个重要的技术:Fragment。在后面会有一章专门介绍Fragment,到时会详细分析MasterDetailFlow模板生成的代码以及如何修改这些代码。

MasterDetailFlow模板自动生成的代码尽管只是个空架子,但仍然有一些默认的代码,直接在手机和平板电脑上运行该程序,会得到不同的界面风格。例如,图5-11是在Nexus 7(7英寸平板电脑)上运行的效果。图5-12是在Android手机上运行的效果。单击图5-12所示列表中的某一个列表项,会用另一个界面显示与该列表项对应的内容,如图5-13所示。

 

▲图5-11 在Nexus 7上运行的效果

 

▲图5-12 在Android手机上显示的效果

 

▲图5-13 显示与某一个列表项对应的内容