注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。
原文链接: http://developer.android.com/training/basics/firstapp/starting-activity.html
一. 启动另一个Activity
在完成了之前的课程后,你已经拥有了一个显示一个Activity(即只有一个屏幕画面)的应用,在这个Activity中有一个文本框和一个按钮。在这节课上,你将在 MainActivity 中添加一些新的代码,这些代码将实现:当用户点击按钮后,可以启动一个新的Activity。
一). 发送按钮的响应
为了响应按钮点击事件,打开布局文件
activity_main.xml
,在
<Button>
标签中,添加
android:onClick
这一属性字段:
< Button android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="@string/button_send" android:onClick ="sendMessage" />
android:onClick 的值为“ sendMessage ”,它在你的 Activity 中的一个方法的名字,当用户点击这个按钮时,系统会调用这个方法。
打开 MainActivity 类(在项目工程的 /src 目录下),然后添加响应的方法:
/** Called when the user clicks the Send button */ public void sendMessage(View view) { // Do something in response to button }
这需要你导入 View 类:
import
android.view.View;
Tip:
在Eclipse中,按下“ Ctrl + Shift + O ”可以自动导入丢失的类(在Mac上的组合键是:“ Cmd + Shift + O ”)。
为了让系统能够将这个方法和它在 android:onClick 属性字段中的方法名这两者相互关联起来,这个方法的特征必须严格地像上述所表示的那样,具体来说,方法的特征有如下几点:
- 必须是 Public
- 返回值为 void
- 只有一个形参 View (这个 View 就是被点击的 View )
接下来,你将会实现这个方法,我们用它来读取文本框中的内容并且将文字发送给另一个 Activity
二). 构建一个Intent
Intent 是一种对象,它是在运行时将两个独立的组件(比如两个 Activity )联系起来的纽带。 Intent 代表了一个应用的某种“意图”,你可以使用Intent去完成很多事情,但通常他们被用来启动另一个Activity。
在 sendMessage() 这一方法中,创建一个新的 Intent 来启动另一个称之为 DisplayMessageActivity 的Activity:
Intent intent = new Intent( this , DisplayMessageActivity. class );
这里的构造函数包含了两个参数:
- 一个 Context 作为第一个参数(这里用 this 的原因是 Activity 是 Context 的一个子类)。
-
应用组件中的某个
Class ,它是系统送达 Intent 的目标(在此例中,对应的是将要被启动的 Activity )
Note:
若你正在使用的是一个集成开发环境(IDE),如:Eclipse,那么对 DisplayMessageActivity 的引用将会引起一个错误,原因是目前这个类还并不存在。我们现在先暂且忽略这个错误,你马上就将创建这个类。
一个
Intent
不仅仅只能允许你启动另一个
Activity
,它还能附带有一些数据给这个
Activity
,在
sendMessage()
这一方法中,使用
findViewById()
这个方法来获取
EditText
控件,并把它的内容交给Intent:
Intent intent = new Intent( this , DisplayMessageActivity. class ); EditText editText = (EditText) findViewById(R.id.edit_message); String message = editText.getText().toString(); intent.putExtra(EXTRA_MESSAGE, message);
Note:
你现在需要导入一些声明: android.content.Intent 和
android.widget.EditText 。稍后你将会定义 EXTRA_MESSAGE 常量。
将Intent发送给其他应用:
这节课中所创建的 Intent ,我们将它称之为“显式的 Intent ”,因为这个
Intent 指明了自己将会发送给哪一个特定的应用组件。然而, Intent 也可以是 “ 隐式的 ”,在这种情况下, Intent 不指明自己期望被发送到哪个组件,但允许任何安装在设备上的应用响应这个 Intent ,只要它的行为的元数据规格与之相匹配,可以通过阅读 : Interacting with Other Apps 获得更多信息。
一个
Intent
携带以键值对形式存放的各种数据类型,在
Intent
中这些键值对被称之为
extras
,
putExtra()
方法中第一个参数对应于键,第二个参数对应于值。
为了让下一个
Activity
可以查询
extras
的数据,你应该使用一个公共常量来定义
Intent
的
extras
中的键。所以在
MainActivity
类的顶端,添加
EXTRA_MESSAGE
的定义:
public class MainActivity extends Activity { public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE" ; ... }
为 Intent extras 的键定义时,将你应用的包名作为前缀是一个好的习惯,这样可以保证他们是唯一的,这有助于你的应用和其他应用进行通信。
三). 启动第二个Activity
为了启动一个
Activity
,调用
startActivity()
方法,并且将你的
Intent
对象传递给它。之后系统接受到函数的调用,并且启动一个被
Intent
所指定的
Activity
实例。
加上了新的代码后,被Send按钮所调用的 sendMessage() 方法的完整代码如下所示:
/** Called when the user clicks the Send button */ public void sendMessage(View view) { Intent intent = new Intent( this , DisplayMessageActivity. class ); EditText editText = (EditText) findViewById(R.id.edit_message); String message = editText.getText().toString(); intent.putExtra(EXTRA_MESSAGE, message); startActivity(intent); }
现在你需要创建 DisplayMessageActivity 类使得它能够正确运行。
四). 创建第二个Activity
使用Eclipse创建第二个类:
- 在工具栏中点击“ New ”
- 在出现的窗口中,打开 “ Android ”文件夹,选择 “ Android Activity ”,点击 “ Next ”
- 选择 “ BlankActivity ” , 点击 “ Next ”
- 填写Activity的细节信息:
-
- Project : MyFirstApp
- Activity Name : DisplayMessageActivity
- Layout Name : activity_display_message
- Title : My Message
- Hierarchial Parent : com.example.myfirstapp.MainActivity
- Navigation Type : None
点击 Finish
图1. Eclipse中创建新Activity的向导
如果你使用的是不同的IDE,或者是命令行,在项目工程中的 “ src/ ”创建一个新的名为“ DisplayMessageActivity.java ”的文件,这个文件紧随最初的 “ MainActivity.java ” 文件。
打开 “ DisplayMessageActivity.java ”,如果你使用的是Eclipse创建的它:
- 这个类已经包含了一个必须的 onCreate() 方法的实现
-
同时还有
onCreateOptionsMenu() 方法的实现,但在这个应用中我们不需要它,所以你可以将它删除
- 同时还有一个 onOptionsItemSelected() 方法的实现,这个方法处理标题栏( Action Bar )的处理上一页( Up )事件时的行为。我们保持它原有的样子。
因为
ActionBar
的APIs仅在
HONEYCOMB
(API Level 11)及更高的版本中才有,所以你必须在
getActionBar()
方法处添加一个条件判断,用来检查当前的平台版本。另外,你必须在
onCreate()
方法处添加一个标签:“
@SuppressLint("NewApi")
”,以此来避免
lint
错误。
现在, DisplayMessageActivity 看上去应该是这样的 :
public class DisplayMessageActivity extends Activity { @SuppressLint( "NewApi" ) @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_display_message); // Make sure we're running on Honeycomb or higher to use ActionBar APIs if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // Show the Up button in the action bar. getActionBar().setDisplayHomeAsUpEnabled( true ); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: NavUtils.navigateUpFromSameTask( this ); return true ; } return super .onOptionsItemSelected(item); } }
如果你使用的IDE不是Eclipse,使用上述代码更新你的 DisplayMessageActivity 类。
所有
Activity
的子类必须实现
onCreate()
方法。当系统创建Activity的实例时,会调用这个方法。在这个方法中,你通过使用
setContentView()
方法定义
activity
的的布局,同时对
activity
的组件进行初始化设置。
Note:
如果你使用的IDE不是Eclipse,你的项目工程将不会包括 setContentView() 所需要的布局文件 activity_display_message,这没有关系,因为你马上将会对这个方法进行更新并且不再需要这个布局。
添加标题字符
如果你使用的是Eclipse,你可以跳过这一节,因为自动创建的模板为新的 activity 提供了标题字符。
如果你使用的IDE不是Eclipse,在“ strings.xml ”添加新 activity 的标题字符:
< resources > ... < string name ="title_activity_display_message" > My Message </ string > </ resources >
添加至清单
在你的清单文件
“
AndroidManifest.xml
”
中,所有
activity
必须通过使用一个
<activity>
标签
被声明。
当你使用Eclipse工具创建这个activity时,它会创建一个默认的条目,如果你使用的不是Eclipse,你需要自己添加这个清单条目,修改后的结果如下:
< application ... > ... < activity android:name ="com.example.myfirstapp.DisplayMessageActivity" android:label ="@string/title_activity_display_message" android:parentActivityName ="com.example.myfirstapp.MainActivity" > < meta-data android:name ="android.support.PARENT_ACTIVITY" android:value ="com.example.myfirstapp.MainActivity" /> </ activity > </ application >
其中
android:parentActivityName
属性字段声明了在应用的逻辑结构中该
activity
的父
activity的名字。系统使用这一属性值来实现默认的导航行为,比如在Android 4.1版本(API Level 16)或更高版本中的
Up navigation
行为。你可以为较旧版本的Android系统提供相同的导航行为,这可以通过使用
Support Library
并且添加
<meta-data>
标签来实现,如同此例所示。
Note:
你的Android SDK应该已经拥有了最新的 Android Support Library,它包含在ADT中。但如果你用的是其他的IDE,你应该在 Adding Platforms and Packages 这一步中已经将它安装好。当在Eclipse中使用模板时,Support Library就被自动地添加到你的项目中了(你可以在 Android Dependencies 下看到这个库的JAR文件)。如果你使用的不是Eclipse,你需要手动将它添加至你的项目,按照如下导引一步步执行即可: setting up the Support Library 。
如果你使用的是Eclipse,你现在已经可以运行这个应用了,但是没有什么事情发生。点击发送按钮会启动第二个 Activity ,但是它使用的是默认的“ Hello World ”模板作为布局。你很快就将更新这个activity,使它显示一个自定义的文本框,若你使用的是其他IDE,不用担心目前自己应用还无法编译的问题。
五). 接受Intent
无论用户是如何被指引到那儿的,每个 Activity 都是被一个 Intent 启动的。你可以通过调用 getIntent() 方法来获得启动你的 activity 的 Intent ,进而收回它所携带的数据。
在 DisplayMessageActivity 类中的的 onCreate() 方法里,提取由 MainActivity发送的数据:
Intent intent =
getIntent();
String message
= intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
六). 显示消息
为了在屏幕上显示消息,创建一个 TextView 控件,然后使用 setText() 方法设置它要显示的文本。之后将 TextView 传递给 setContentView() ,这样 TextView 就成为了这个activity的根View。
DisplayMessageActivity 的 onCreate() 方法的完整代码如下:
@Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); // Get the message from the intent Intent intent = getIntent(); String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE); // Create the text view TextView textView = new TextView( this ); textView.setTextSize( 40 ); textView.setText(message); // Set the text view as the activity layout setContentView(textView); }
现在你可以运行这个应用。当它打开后,在文本框里输入一些文字,点击发送,然后这些文字将会在第二个 activity 中显示出来。
图2. 在Android4.0设备上的运行结果
就是这样,你已经构建好了你的第一个应用了!