启动另一个Activity
在完成了之前的课程之后,你现在已经有了一个简单的APP,简单地显示一个Activity,上面有一个文本框和一个按钮。在本课,你将在MainActivity里添加一些代码,当按钮被点击的时候,可以启动一个新的Activity。
响应Send按钮
为了使按钮响应点击事件,需要在<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/文件夹下),添加下面的方法:
/** 当用户点击Send按钮时调用 */
public void sendMessage(View view) {
// Do something in response to button
}
这个方法名必须与android:onClick里的值完全一样。这个方法还具有如下特征:
类型是public
返回值是 void
参数是View类型,且只有一个参数(参数view就是你点击的那个View引用)
接下来,你需要更改这个方法去读取文本框的内容,并把内容发送给另一个Activity。
创建一个Intent
一个Intent就是一个为各个组件(例如两个 activity)提供运行时通信的对象。它表示某个app“意图做某件事情”。你可以使用intent做各种各样的事情,通常用于启动另一个activity。
在sendMessage()方法里,创建一个Intent,去启动一个叫DisplayMessageActivity的activity:
Intent intent = new Intent(this, DisplayMessageActivity.class);
然后导入包引用:
import android.content.Intent;
提示:在Eclipse里,使用快捷键Ctrl+Shift+O自动导入缺失包。
Intent的构造函数有两个参数:
Context:第一个参数(此处使用this,因为Activity类是Context的子类。)
Class:第二个参数,表示系统发送此Intent的目标组件的类名。(在本例中,就是要启动的activity)
注意:在Eclipse中,引用DisplayMessageActivity,会引发错误。请先忽略错误,一会儿我们再建这个类。
另外,此处创建的Intent称之为显示Intent,因为我们明确指定了目标组件。还有一种隐式Intent,不明确指定目标组件,而是通过设置其他一些参数,然后由手机上安装的APP去匹配这些参数,如果匹配成功,就由这样的APP作为目标组件接收Intent。具体可以参考以后的课程。
一个Intent不仅可以允许你启动一个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);
注意:需要导入包android.widget.EditText。一会儿我们再定义EXTRA_MESSAGE常量。
一个Intent可以收集各种数据类型,以键值对的形式存放,美其名曰extras。putExra()方法就是把键作为第一个参数,把值作为第二个参数。
为了使被启动的Activity能够读取这个附加数据,你需要把这个键常量值定义为公有的。所以我们在类MainActivity的前面添加EXTRA_MESSAGE定义:
public class MainActivity extends ActionBarActivity {
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
...
}
一个比较好的习惯就是使用你的APP所在包名作为键定义的前缀。这样可以保证在系统中这个定义是唯一的,与其他APP交互而不会产生冲突。
启动第二个Activity
为了启动一个activity,调用函数startActivity(),并且将Intent作为参数传进去。系统收到调用后,将启动Intent指定的activity。
按照上面的描述,Send按钮单击事件响应函数sendMessage()完整形式如下:
/** 当用户点击Send按钮时调用 */
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创建一个新的activity:
1. 点击工具栏上的New ;
2. 在弹出的窗口里,打开Android折叠项,选择AndroidActivity,选择 Next。
3. 选择 BlankActivity ,然后点击 Next.
4. 填写Activity的细节信息:
Project: MyFirstApp
Activity Name:DisplayMessageActivity
Layout Name:activity_display_message
Fragment Layout Name:fragment_display_message
Title: My Message
Hierarchial Parent:com.example.myfirstapp.MainActivity
Navigation Type: None
点击 Finish.
如果你使用了不同的IDE工具的话,请在src/文件下创建DisplayMessageActivity.java文件,与MainActivity.java在同一目录下。
打开DisplayMessageActivity.java文件。如果你使用了Eclipse来创建的话:
类中已经包含需要的onCreate()方法。一会儿你需要更改这个方法。
还有一个onCreateOptionsMenu()方法,在本课中用不到,你可以直接删除它。
还有一个onOptionsItemSelected()方法,这个方法处理了Action Bar的导航功能。保留这个方法不变。
还有一个继承自Fragment的PlaceholderFragment类。最终我们不需要这个类。
Fragment将APP的功能和UI变成了可复用的模块。具体细节,以后课程会讲到,也可以参考API帮助文档。这个activity的最终版本不会用到Fragment。
注意:你创建的activity可能和我的不一样,这是因为你没有更新到最新的ADT插件版本。请首先更新ADT插件到最新版本。
DisplayMessageActivity类如下所示:
public class DisplayMessageActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_message);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// 这里处理动作栏的菜单项. 动作栏会自动处理Home/UP按钮,只要你在//AndroidManifest.xml中指定了父Activity.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() { }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_display_message,
container, false);
return rootView;
}
}
}
如果你使用的IDE不是Eclipse,请把DisplayMessageActivity的代码更改成如上所示。
所有的Activity的子类必须实现onCreate()方法。当创建一个新的Activity实例的时候,系统会调用这个方法。在这里,你需要调用setContentView()方法来定义这个activity的布局,同时你应该初始化activity的组件。
注意:如果你使用的IDE不是Eclipse,你的工程可能没有包含setContentView()所需要的activity_display_message布局文件。但是没有关系,本课中用不到这个布局文件。
添加标题字符串
如果你使用的是Eclipse,你可以跳过本小节,因为模板会为新的activity自动创建标题字符串。
如果你使用的不是Eclipse,那么请打开strings.xml,并且添加如下字符串:
<resources>
...
<string name="title_activity_display_message">My Message</string>
</resources>
将新的activity添加到配置文件中
所有的activity必须在配置文件AndroidManifest.xml中声明。声明时使用<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。系统使用此属性来决定导航行为,比如android4.1版本(API 16)或者更高的版本上的“向上导航”功能(其实主要就是点击左上角的home图标按钮返回到哪一个activity)。在稍低版本上,你可以使用支持库并且添加如本例所示的<meta-data>元素。
如果你使用了Eclipse作为开发工具,现在你可以运行app。点击 Send按钮,将启动第二个activity,界面上显示”Hello World”。很快你就可以更改这个activity,让它显示一个我们自己定制的文本view。
接收一个Intent
每一个Activity都是由一个Intent唤醒的,无论用户是如何启动这个activity的。你可以通过方法getIntent()获得到那个启动你的activity的Intent,然后可以取得里面的数据。
在类DisplayMessageActivity的onCreate()方法里,获得由MainActivity发送过来的Intent,并提取出消息:
Intent intent = getIntent();
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
显示消息
为了将消息显示到屏幕上,创建一个TextView组件,使用setText()设置文本内容。然后将这个TextView作为参数传递给方法setContentView(),使这个TextView成为这个activity布局视图的根view。
DisplayMessageAcvitiy完整的onCreate()方法形式如下:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 从Intent中获得消息
Intent intent = getIntent();
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
// 创建TextView组件
TextView textView = new TextView(this);
textView.setTextSize(40);
textView.setText(message);
// 设定textView作为activity的根view
setContentView(textView);
}
现在你可以运行你的APP了。当界面出现时,在文本框中输入一段文本,然后点击 Send按钮,这段文本就会出现在第二个activity上。
Figure 2. Both activities inthe final app, running on Android 4.4.
目前为止,你已经建立了你的第一个APP!
想学到更多的东西,请关注后续的课程。