活动是最容易吸引用户的地方,它是一种可以包含用户界面的组件,主要用于和用户进行交互。一个应用程序可以包含零个或多个活动,但不含任何活动的应用程序少。
1.创建活动
在java目录下的包中右键—>New—>Activity—>Empty Activity,会弹出一个创建活动的对话框,我们将活动命名为FirstActivity,并且不要勾选 Generate Layout File 和 Launcher Activity 这两个选项。
给Button指定id为button_1。通过Design来预览界面
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
所有的活动都需要在 AndroidManifest.xml 中进行注册才能生效,而实际上 FirstActivity 已经在 AndroidManifest.xml 中注册过了,打开 AndroidManifest.xml 可以看到
可以看到,活动的注册声明都要放在
Toast 是 Android 系统提供的一种非常好用的提醒方式,在程序中可以使用它将一些短小的信息通知给用户,这些信息会在一段时间后自动消失,并且不会占用任何屏幕空间,我们现在尝试一下如何在活动中使用 Toast.我们在界面中有一个按钮,需要按下按钮时显示 Toast。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Button button = (Button)findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"You clicked this Button",Toast.LENGTH_SHORT).show();
}
});
这里定义一个Button变量button来接受通过findViewById找到布局中的Button,然后将View强制转换为Button,接着给button设置一个监听器。当按下时执行监听方法中Toast.makeTexT().show()方法,从而将短消息以 Toast 的形式显示出来。这里Toast.maktText()方法中需要传入三个方法,第一个是环境,也就是上下文;第二个是需要显示的短消息;第三个是短消息的类型,有两种,一个Toast.LENGTH_SHORT,一个Toast.LENGTH_LONG。
手机和电脑不同,它没有办法让所有的功能选项显示在屏幕中,它的屏幕很有限,因此充分地利用屏幕空间在手机界面设计中就显得非常重要了。Android给我们提供了一种方式,可以让菜单都能得到展示的同时,还能不占用任何的屏幕空间。
首先在res目录下新建一个 menu 文件夹,右击 res 目录—>New—>Directory,输入文件夹名menu,点击OK。接着在这个文件夹下再新建一个名叫 main 的菜单文件,右击 menu 文件夹—>New—>Menu resource file。在main.xml中添加下面代码。
这里我们创建了两个菜单项,其中
接着重新回到 FirstActivity 中来重写 onCreateOptionsMenu()方法,重写方法可以使用 Ctrl+O快捷键( Mac 系统是 control + O)。然后在 onCreateOptionsMenu()方法中编写如下代码:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main,menu);
return true;
}
通过getMenuInflater()方法获得 MenuInflater 对象,再调用它的 inflate() 方法就可以给当前活动创建菜单了。inflate()方法接受两个参数,第一个参数用于指定我们通过哪一个资源文件来创建菜单,这里当然传入 R.menu.main 。第二个参数用于指定我们的菜单项将添加到哪一个 Menu 对象中,这里直接使用 onCreateOptionMenu() 方法中传入的 menu 参数。然后给这个方法返回 true ,表示允许创建的菜单显示出来,如果返回了 false ,创建的菜单将无法显示。
当然,仅仅让菜单显示出来还是不够的,我们定义菜单不仅是为了看的,关键是要菜单真正可用才行,因此还要再定义菜单响应事件。再 FirstActivity 中重写 onOptionsItemSelected() 方法:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.item_add:
Toast.makeText(MainActivity.this, "You clicked ADD", Toast.LENGTH_SHORT).show();
break;
case R.id.item_remove:
Toast.makeText(MainActivity.this, "You clicked REMOVE", Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
重新运行程序你会发现标题栏右边多了三点,点击就可以打开菜单项
按一下 Back 键就可以摧毁当前的活动。但是如果你不想通过返回键摧毁活动还可以通过finish()方法,我们在活动中调用一下这个方法就可以摧毁当前活动。修改按钮监听器中的代码,如下所示:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Button button = (Button)findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
Intent 可以帮助我们从一个活动跳转到另外一个活动.
你应该已经对创建活动的流程比较熟悉了,那我们现在快速地在项目中再创建一个活动。
Intent 有多个构建函数重载,其中一个是 Intent(Context packageContext,Classcls)。这个构造函数接受两个参数,第一个参数 Context 要求提供一个启动活动的上下文,第二个参数Class 则是指定想要启动的目标活动,通过这个构造寒素就可以构建出 Intent 的“意图”。然后我们应该怎么使用这个 Intent 呢? Activity类中提供了一个 startActivity()方法,这个方法是专门用于启动活动,它接受一个 Intent 参数,这里我们将构建好的 Intent 传入 startActivity() 方法就可以启动目标活动了。
修改 FirstActivity 中的按钮的点击事件,代码如下所示:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
});
运行程序点击BUTTON1,活动跳转
相比如显示的 Intent ,隐式 Intent 则含蓄了许多,它并不明确指出我们想要启动哪个活动,而是指定了一系列更为抽象的 action 和 category 等信息,然后交由系统去分析这个 Intent,并帮助我们找到合适的活动去启动。
什么叫做合适的活动呢?简单的来说就是可以响应我们这个隐式 Intent 的活动,那么目前 SecondActivity 可以响应什么样的隐式 Intent 呢? 现在还是什么都响应不了,因为我们没有给这个活动定义。
通过再
在
标签则包含了一些附加的信息,更精确地指明了当前的活动能够响应的 Intent 中还可能带有的 category 。只有
修改按钮事件,代码如下:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent("com.example.thesecond.ACTION_START");
intent.addCategory("com.example.thesecond.MY_CATEGORY");
startActivity(intent);
}
});
可以看到效果和显示的一样。
上面用隐式 Intent 来启动自己程序的活动,但实际上隐式 Intent 还有更多的内容需要你去了解,本节我们就来展开介绍一下。
使用隐式 Intent ,我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动,这使得 Android 多个应用程序之间的功能共享成为了可能。比如说你的应用程序中需要展示一个网页,这时你没有必要自己去实现一个浏览器(事实上也不太可能),而是只需要调用系统的浏览器拉力打开这个网页就行了。
修改第一个活动中的点击事件的代码,如下所示:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent =new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});
这里我们首先指定了 Intent 的 action 是 Intent.ACTION.VIEW ,这是一个 Android 系统内置的动作,其常量值为 android.intent.action.VIEW。然后通过 Uri.parse() 方法,将一个网址字符串解析成一个 Uri 对象,再调用 Intent 的 setData() 方法将这个Uri 对象传递进去。
重新运行程序,再MainActivition 界面点击按钮就可以看到打开了浏览器。
上述代码中,setData() 方法的并不复杂,它就收一个Uri对象,主要用于当前 Intent 正在操作的数据,而这些数据通常都是以字符串的形式传到 Uri.parse() 方法中解析的。
与此对应的,我们还可以在
android:scheme。用于指定数据的协议部分,如上例的的http部分。
android:scheme。用于指定数据的主机名部分,例如上例中的 www.baidu.com部分。
android:prot。用于指定数据的端口部分,一般紧跟在主机名后。‘
android:path。用于指定主机和端口后的部分,如一段网址中跟在域名端口后的部分。
android:mimeType。用于指定可以处理的数据类型,允许使用通配符的方式进行指定。
只有标签中指定的内容和 Intent 中携带的 Data 完全一致时,当前活动才能够响应该 Intent。不过一般在标签中都不会指定过多的内容,如上面浏览器示例中,其实只需要指定 android:scheme 为 http,就可以响应所有的 http 协议的 Intent 了。
新建一个名为ThirdActivity的活动。
在AndroidManifest.xml中加入下面代码:
会提示我们有两个App可以打开:
可以看到,系统自动弹出了一个列表,显示了目前能够响应这个 Intent 的所有程序。选择Chrome会像之前一样打开浏览器,并显示百度首页,而如果选择了 The Second ,则会启动ThirdActivity。虽然我们声明了 ThirdActivity 可以响应打开网页的 Intent ,但实际上这个活动并没有加载显示网页的功能,所以在真正的项目中尽量不要出现这种有可能舞蹈用户的行为,不然会让用户对我们的应用产出负面的印象。
除了http协议外,我们还可以指定很多其他协议,比如 geo 表示显示地理位置,tel 表示拨打电话。下面的代码展示了如何在我们的程序中调用系统拨号页面。
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent =new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
});
在MainActivity中按钮事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent =new Intent(MainActivity.this,SecondActivity.class);
intent.putExtra("param","data_1");
startActivity(intent);
}
});
用显示的 Intent 跳转,同时用 intent 的 putExtra() 方法来将数据存起来,该方法第一个为参数为键,第二个参数为值。
在SecondActivity中接受并打印日志
private static final String TAG = "SecondActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Intent intent = getIntent();
String data = intent.getStringExtra("param");
Log.d(TAG, data);
}
首先可以通过 getIntent() 方法来获取用于启动 SecondActivity 的 Intent ,然后通过 getStringExtra() 方法来通过键来得到值。最后将值打印在日志中。
在MainActivity中按钮代码:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent =new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent,1);
}
});
其中 startActivityForResult() 方法的期望在活动被摧毁之前能够返回一个结果给上一个活动。
活动被回收它的数据也会被回收,android提供了一个 onSaveInstanceState() 方法,这个方法携带一个 Bundle 类型的参数,可以用它来保存数据。
保存数据:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("param2","保存的数据");
}
在onCreate中加入获取数据代码:
if(savedInstanceState!=null){
String data_save=savedInstanceState.getString("param2");
Log.d(TAG, data_save);
}