活动是什么
Activity是一种可以包含用户界面的组件,主要用于和用户进行交互。一个应用程序中可以包含零个或多个活动
活动的基本用法
首先新建一个Android项目,选择Add NoActivity。
2.1手动创建活动
在所创建的包下新建一个Empty Activity,因为这是手动创建活动,所以不要勾选Generate Layout File 和 Launcher Activity。Generate Layout File会自动为你所创建的活动创建一个对应的布局文件,Launcher Activity会自动将你所创建的活动设置为当前项目的主活动。
注:项目中的任何活动都应该重写Activity的onCreate() 方法,AndroidStudio自动帮我们重写了这个方法。但只是简单的调用了父类的onCreate() 方法,后面我们还需要加入自己的想法。
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
2.2创建和加载布局
Android程序的设计讲究逻辑和视图分离,最好每个活动都能对应一个布局,布局就是用来显示界面内容的,接下来我们来手动创建一个布局。 在res目录中new一个Directory,创建一个名为layout的目录,在这个目录下创建一个Layout resource file,此时会弹出一个新建布局资源文件的窗口,我们将布局文件命名为first_layout 根元素默认选择LinearLayout即可。 此时我们会看到Android Studio为我们提供的可视化布局编辑器。最右边有三个选项,其中Design是当前的可视化布局编辑器,在这里可以预览当前布局也可以通过拖拽的方式编辑布局,Code则是通过XML文件的方式来编辑布局,  切换到Code下。可以看到布局中已经存在了一个LinearLayout元素,这是因为创建布局文件时选择了LinearLayout作为根元素。
添加一个按钮:添加一个Button元素,并在其内部添加属性。android:id是给当前元素定义一个唯一的标识符,android:layout_width指定了当前元素的宽度,match_parent让当前元素与父元素一样宽。match_parent表示当前元素的高度只要能刚好包含里面的内容就好。android:text指定了元素中显示的文字内容。
<Button
android:id="@+id/button_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 1" />
在活动中加载这个布局。在所创建的Activity中的onCreate() 中加入以下代码
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_layout);
}
}
这里调用setContentView() 方法给当前活动加载一个布局,在方法中传入一个id。项目中添加的任何资源都会在R文件中生成一个相应的资源id,只需要调用R.layout.first_layout就可以得到first_layout.xml布局的id。
2.3在AndroidManifest文件中注册
所有活动需要在AndroidManifest中注册才能生效
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.activitytest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ActivityTest">
<activity android:name=".FirstActivity"></activity>
</application>
</manifest>
配置主活动,在在<activity> 标签的内部加入<intent- filter> 标签,除此之外,我们还可以使用android:label指定活动中标题栏的内容,标题栏是显示在活动最顶部的,待会儿运行的时候你就会看到。需要注意的是,给主活动指定的label 不仅会成为标题栏中的内容,还会成为启动器( Launcher )中应用程序显示的名称。
<activity
android:name=".FirstActivity"
android:label="This is FirstActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
现在就可以运行这个程序啦
2.4在活动中使用Toast
Toast是Android系统提供的–种非常好的提醒方式,在程序中可以使用它将一些短小的信息通知给用户,这些信息会在一段时间后自动消失,并且不会占用任何屏幕空间. 使用Toast首先需要定义一个弹出Toast的触发点,以界面上的这个按钮为例.在onCreate() 方法中添加如下代码:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_layout);
Button button1 = (Button) findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(FirstActivity.this, "You clicked Button 1", Toast.LENGTH_SHORT).show();
}
});
}
2.5在活动中使用Menu
Android 给我们提供了一种方式,可以让菜单都能得到展示的同时,还能不占用任何屏幕空间。 首先在res 目录下新建一个menu文件夹,右击res 目录→New→Directory,输入文件夹名menu,点击OK。接着在这个文件夹下再新建一个名叫main 的菜单文件,右击menu文件夹→New →Menu resource file. 然后在main.xml中添加如下代码:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/add_item"
android:title="Add"/>
<item
android:id="@+id/remove_item"
android:title="Remove"/>
</menu>
创建两个菜单选项 item标签用来创建具体的某一个菜单项 接着重新回到FirstActivity中来重写onCreateOptionsMenu() 方法,
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main,menu);
return true;
}
通过getMenuInflater() 方法能够得到MenuInflater对象,再调用它的inflate() 方法就可以给当前活动创建菜单了。定义菜单响应事件。在FirstActivity中重写onOptionsItemSelected() 方法:
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.add_item:
Toast.makeText(this, "You clicked Add", Toast.LENGTH_SHORT).show();
break;
case R.id.remove_item:
Toast.makeText(this, "You clicked Remove", Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
2.6销毁一个活动
按Back键或修改按钮监听器中的代码即可
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
Intent的使用
跳转到其他的活动 在ActivityTest项目上再创建一个活动,命名为SecondActivity,勾选Generate Layout File,给布局文件命名为second_layout,不勾选Launcher Activity选项。 将second_layout.xml代码替换
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 2"
/>
</LinearLayout>
在此活动中定义了一个按钮Button 2 ,SecondActivity中的代码已经自动生成了一部分,保持不变就好
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
}
在AndroidManifest.xml中注册,Android Studio已经帮我们完成了注册,由于SecondActivity不是主活动,因此不需要配置<inter-filter> 标签里的内容。
Intent是Android程序中各组件之间进行交互的一-种重要方式,它不仅可以指明当前组件想,要执行的动作,还可以在不同组件之间传递数据。Intent - -般可被用于启动活动、启动服务以及发送广播等场景。
显示Intent
Intent有多个构造函数的重载,其中一个是Intent (Context packageContext, Class<?>cls) 。这个构造函数接收两个参数,第-一个参数Context要求提供-一个启动活动的上下文,第二个参数Class则是指定想要启动的目标活动,。 然后我们应该怎么使用这个Intent呢? Activity 类中提供了一个startActivity() 方法,这个方法是专门用于启动活动的,它接收一个Intent参数,这里我们将构建好的Intent 传入startActivity() 方法就可以启动目标活动了。 修改FirstActivity中按钮的点击事件,在FirstActivity的基础上打开SecondActivity
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
}
});
此时 点击FirstActivity中的按钮就可以进入SecondActivity活动界面了
隐式Intent
相比于显式Intent,隐式Intent 则含蓄了许多,它并不明确指出我们想要启动哪一个活动,而是指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并帮我们找出合适的活动去启动。 通过在<activity> 标签下配置<intent- filter> 的内容,可以指定当前活动能够响应的action和category,打开AndroidManifest.xml,添加如下代码:
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
只有和中的内容同时能够匹配上Intent中指定的action和category时,这个活动才能响应该Intent。 修改FirstActivity中按钮的点击事件:
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.activitytest.ACTION_START");
startActivity(intent);
}
});
可以看到,我们使用了Intent 的另一个构造函数,直接将action的字符串传了进去,表明我们想要启动能够响应com. example. activitytest.ACTION_ START这个action的活动。那前面不是说要<action> 和<category> 同时匹配上才能响应的吗?怎么没看到哪里有指定category呢?这是因为android . intent. category . DEFAULT是一种默认的category,在调用startActivity()方法的时候会自动将这个category添加到Intent中。 每个Intent中只能指定一个 action,但却能指定多个category。
添加category只需要调用Intent中的addCategory() 方法。如下 : 修改FirstActivity中的按钮点击事件
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.activitytest.ACTION_START");
intent.addCategory("com.example.activitytest.MY_CATEGORY");
startActivity(intent);
}
});
在SecondActivity中intent-filter标签中声明可以响应这个category
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.example.activitytest.MY_CATEGORY" />
</intent-filter>
</activity>
更多隐式Intent的用法
使用隐式Intent,我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动,这使得Android多个应用程序之间的功能共享成为了可能。比如说你的应用程序中需要展示一个网页,这时你只需要调用系统的浏览器来打开这个网页就行了。
修改FirstActivity中按钮的点击事件,
button1.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-filter> 标签中再配置一个<data> 标签,用于更精确地指定当前活动能够响应什么类型的数据。<data> 标签中主要可以配置以下内容。
- android:scheme。用于指定数据的协议部分,如上例中的http部分。
- android: host。用于指定数据的主机名部分,如上例中的www.baidu.com部分。
- android: port。用于指定数据的端口部分,一般紧随在主机名之后。
- android:path。用于指定主机名和端口之后的部分,如- -段网址中跟在域名之后的内容。
- android: mimeType。用于指定可以处理的数据类型,允许使用通配符的方式进行指定。
只有<data> 标签中指定的内容和Intent 中携带的Data完全一致时, 当前活动才能够响应该Intent。不过一般在<data> 标签中都不会指定过多的内容,如上面浏览器示例中,其实只需要指定android:scheme为http,就可以响应所有的http协议的Intent了。 为了让你能够更加直观地理解,我们来自己建立一个活动,让它也能响应打开网页的Intent。 重新创建一个活动,ThirdActivity并勾选Generate Layout File,给布局文件命名为third_layout。编辑third_layout.xml,替换里面的代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 3"
/>
</LinearLayout>
修改ThirdActivity的注册信息
<activity android:name=".ThirdActivity"
tools:ignore="AppLinkUrlError">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"/>
</intent-filter>
</activity>
我们在ThirdActivity的<intent- filter> 中配置了当前活动能够响应的action是Intent.ACTION_ VIEW的常量值,而category则毫无疑问指定了默认的category值,另外在<data> 标签中我们通过android: scheme指定了数据的协议必须是http协议,这样ThirdActivity应该就和浏览器一 样,能够响应一个打开网页的Intent 了。
除了http 协议外,我们还可以指定很多其他协议,比如geo表示显示地理位置、tel 表示拨打电话。下面的代码展示了如何在我们的程序中调用系统拨号界面。
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
});
向下一个活动传递数据
Intent还可以在启动活动的时候传递数据在启动活动时传递数据的思路很简单,Intent 中提供了一系列putExtra() 方法的重载,可以把我们想要传递的数据暂存在Intent 中,启动了另一个活动后,只需要把这些数据再从Intent中取出就可以了。比如说FirstActivity 中有一个字符串,现在想把这个字符串传递到Second-Activity中,你就可以这样编写:
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String data = "Hello SecondActivity";
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("extra_data", data);
startActivity(intent);
}
});
这里我们还是使用显式Intent的方式来启动SecondActivity,并通过putExtra( ) 方法传递了一个字符串。注意这里putExtra() 方法接收两个参数,第一个参数是键,用于后面从Intent 中取值,第二个参数才是真正要传递的数据。 然后我们在SecondActivity中将传递的数据取出,并打印出来,代码如下所示:
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity", data);
}
}
} 首先可以通过getIntent() 方法获取到用于启动SecondActivity 的Intent, 然后调用getString Extra() 方法, 传人相应的键值,就可以得到传递的数据了。这里由于我们传递的是字符串,所以使用getStringExtra() 方法来 获取传递的数据。如果传递的是整型数据,则使用getIntExtra() 方法;如果传递的是布尔型数据,则使用getBooleanExtra() 方法,以此类推。
返回数据给上一个活动
通过Activity中有一个startActivityForResult() 的方法可以实现 startActivityForResult() 方法接收两个参数,第一个参数还是Intent , 第二个参数是请求码,用于在之后的回调中判断数据的来源。修改FirstActivity 中按钮的点击事件,代码如下所示:
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(intent , 1);
}
});
这里我们使用了startActivityForResult() 方法来启动SecondActivity,请求码只要是一个唯一值就可以了,这里传入了1。接下来我们在SecondActivity 中给按钮注册点击事件,并在点击事件中添加返回数据的逻辑,代码如下所示:
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Button button2 = (Button) findViewById(R.id.button_2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.putExtra("data_return", "Hello FirstActivity");
setResult(RESULT_OK , intent);
finish();
}
});
}
}
可以看到,我们还是构建了一个Intent,只不过这个Intent仅仅是用于传递数据而已,它没有指定任何的“意图”。紧接着把要传递的数据存放在Intent 中,然后调用了setResult() 方法。这个方法非常重要,是专门用于向上一个活动返回数据的。setResult() 方法接收两个参数,第一个参数用于向上一个活动返回处理结果,一般只使用RESULT_ 0K或RESULT _CANCELED这两个值,第二个参数则把带有数据的Intent 传递回去,然后调用了finish() 方法来销毁当前活动。 由于我们是使用startActivityForResult() 方法来启动SecondActivity的,在SecondActivity被销毁之后会回调上一个活动的onActivityResult() 方法,因此我们需要在FirstActivity中重写这个方法来得到返回的数据
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
String returnedData = data.getStringExtra("data_return");
Log.d("FirstActivity", returnedData);
}
break;
default:
}
}
onActivityResult() 方法带有三个参数,第-个参数requestCode,即我们在启动活动时传入的请求码。第二个参数resultCode, 即我们在返回数据时传人的处理结果。第三个参数data,即携带着返回数据的Intent。 由于在一个活动中有可能调用startActivityForResult() 方法去启动很多不同的活动,每一个活动返回的数据都会回调到onActivityResult() 这个方法中,因此我们首先要做的就是通过检查requestCode的值来判断数据来源。确定数据是从SecondActivity返回的之后,我们再通过resultCode的值来判断处理结果是否成功。最后从data中取值并打印出来,这样就完成了向上一个活动返回数据的工作。
如果用户是通过按下Back键回到FirstActivity,可以通过在SecondActivity中重写onBackPressed( ) 方法来解决这个问题,代码如下所示:
@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("data_return", "Hello FirstActivity");
setResult(RESULT_OK, intent);
finish();
}
用户按下Back键就会执行onBackPressed( ) 中的方法
|