【Android Developers Training】 4. 启动另一个Activity
注:本文翻译自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设备上的运行结果
就是这样,你已经构建好了你的第一个应用了!