Android从入门到精通——学习笔记:Chapter06-基本程序单元Activity

温馨提示:关于Android的很多内容都已更新换代,但是整体的逻辑框架没有大的改变,所提供的文章仅供大家对于Android有个大体的认识与了解。作者也在不断学习的阶段,希望大家一起进步!

Chapter 06 基本程序单元Activity

在前面介绍的实例中已经应用过Activity,不过那些实例中的所有操作都是在一个Activity中进行的,在实际的应用开发中,经常需要包含多个Activity,而且这些Activity之间可以相互跳转或传递数据,本章将对Activity进行介绍。

6.1 Activity概述

在Android应用中,提供了4大基本组件,分别是Activity、Service、BroadcastReceiver和ContentProvider。其中Activity是Android应用最常见的组件之一,它的中文意思是活动。在Android中,Activity代表手机或者平板电脑中的一屏,它提供了和用户交互的可视化界面。在一个Activity中,可以添加很多组件,这些组件负责具体的功能。

在一个Android应用中,可以有多个Activity,这些Activity组成了Activity栈(Stack),当前活动的Activity位于栈顶,之前的Activity被压入下面,成为非活动Activity,等待是否可以被恢复为活动状态。在Activity的生命周期中,有如下表所示的4个重要状态:

Activity的4个重要状态
状态描述
运行状态当前的Activity,位于Activity栈顶,用户可见,并且可以获得焦点
暂停状态失去焦点的Activity,仍然可见,但是在内存低的情况下,不能被系统killed(杀死)
停止状态该Activity被其他Activity所覆盖,不可见,但是它仍然保存所有的状态和信息。当内存低的情况下,它将会被系统killed(杀死)
销毁状态该Activity结束,或Activity所在的虚拟器进程结束

在了解Activity的4个重要状态后,再来看下图,下图显示了一个Activity的重要状态,以及祥光的回调方法:

在这里插入图片描述

在上图中,矩形方块表示的内容为可以被回调的方法,而有底色的椭圆形则表示Activity的重要状态。从该图可以看出,在一个Activity的生命周期中有一些方法会被系统回调,这些方法的名称及其描述如下表所示:

Activity生命周期中的回调方法
方法名描述
onCreate()在创建Activity时被回调。该方法是最常见的方法,在Android Studio中创建Android项目时,会自动创建一个Activity,在该Activity中,默认重写了onCreate(Bundle savedInstanceState)方法,用于对该Activity执行初始化
onSatrt()启动Activity时被回调,也就是当一个Activity变为可见时被回调
onResume()当Activity由暂停状态恢复为活动状态时调用。调用该方法后,该Activity位于Activity栈的栈顶。
onPause()暂停Activity时被回调。该方法需要被非常快速地执行,因为直到该方法执行完毕后,下一个Activity才能被恢复。在该方法中,通常用于持久保存数据。例如,当我们正在玩游戏时,突然来了一个电话,这时就可以在该方法中将游戏状态持久保存起来
onRestart()重新启动Activity时被回调,该方法总是在onStart()方法以后执行
onDestroy()销毁Activity时被回调

说明:在Activity中,可以根据程序的需要来重写相应的方法。其中,onCreate()和onPause()方法时最常用的,经常需要重写这两个方法。

6.2 创建、配置、启动和关闭Activity

在Android中,Activity提供了与用户交互的可视化界面。在使用Activity时,需要先对其进行创建和配置,然后才可以启动或关闭Activity。下面将详细介绍创建、配置、启动和关闭Activity的方法。

6.2.1 创建Activity

创建Activity的基本步骤如下:

(1)创建一个Activity,一般时继承android.app包中的Activity类,不过在不同的应用场景下,也可以继承Activity的子类。例如,在一个Activity中,如果只实现一个列表,就可以放该Activity继承ListActivity;如果只实现选项卡效果,就可以让Activity继承TabActivity。创建一个名为MyActivity的Activity,具体代码如下:

import android.app.Activity;
public class MyActivity extends Activity {
	//...
}

(2)重写需要的回调方法。通常情况下,都需要重写onCreate()方法,并且在该方法中调用setContentView()方法设置要显示的页面。例如,在步骤(1)中创建的Activity中,重写onCreate()方法,并设置要显示的页面为activity_my.xml,具体代码如下:

@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_my.xml);
}

另外,使用Android Studio也可以很方便地创建Activity,具体步骤如下:

(1)在Module的包名(如com.example)节点上点击,在弹出的快捷菜单上依次选择New→Activity→Empty View Activity,如下图所示:

在这里插入图片描述

(2)在弹出的对话框中修改Activity的名称,如下图所示:

在这里插入图片描述

(3)单击Finish按钮即可创建一个空的Activity,然后就可以在该类中重写需要的回调方法。

6.2.2 配置Activity

使用Android Studio向导创建Activity后,会自动在AndroidMainfest.xml文件中配置该Activity。如果没有在AndroidManifest.xml文件中配置,而又在程序中启动了该Activity,就会抛出异常。

具体的配置方法是在<application></application>标记中添加<activity></activity>标记实现(每个Activity对应一个<activity></activity>标记),<activity>标记的基本格式如下:

<activity
	android:name="实现类"
	android:label="说明性文字"
	android:theme="要应用的主题"
	...
	>
	...
</activity>

从上面的格式可以看出,配置Activity时通常需要指定以下几个属性:

  1. android:name:指定对应的Activity实现类
  2. android:label:为该Activity指定标签
  3. android:theme:设置要应用的主题

说明:如果该Activity类在<manifest>标记的package属性指定的包中,则android:name属性的属性值可以直接写类名,也可以是“.类名”的形式;如果在package属性指定包的子包中,则属性值需要设置为“.子包序列.类型”或者是完整的类名(包括包路径)。

6.2.3 启动和关闭Activity
1. 启动Activity

启动Activity分为以下两种情况:

(1)在一个Android应用中,只有一个Activity时,那么只需要在AndroidMainfest.xml文件中对其进行配置,并且将其设置为程序的入口。这样,当运行该项目时,将自动启动该Activity。

(2)在一个Android的应用中,存在多个Activity时,需要应用startActivity()方法来启动需要的Activity。startActivity()方法的语法格式如下:

public void startActivity(Intent intent)

该方法没有返回值,只有一个Intent类型的入口参数,Intent是Android应用里各组件之间的通信方式,一个Activity通过Intent来表达自己的“意图”。在创建Intent对象时,需要指定想要被启动的Activity。

说明:关于Intent将在下章进行详细介绍。

例如,要启动一个名称为DetailActivity的Activity,可以使用下面的代码:

Intent intent = new Intent(MainActivity.this, DetailActivity.class);
startActivity(intent);
2. 关闭Activity

在Android中,如果想要关闭当前的Activity,可以使用Activity类提供的finish()方法。finish()方法的语法格式如下:

public void finish()

该方法的使用比较简单,既没有入口参数,也没有返回值,只需要在Activity中相应的事件中调用该方法即可。例如,想要在单击按钮时关闭该Activity,可以使用下面的代码:

Button button =  (Button) findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View v) {
		finish();
	}
});

说明:如果当前的Activity不是主活动,那么执行finish()方法后,将返回到调用它的那个Activity;否则将返回主屏幕中。

下面编写一个小例子(模拟喜马拉雅FM跳转至忘记密码界面)进行演示:

(1)主活动界面布局文件activity_main.xml内容如下:

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/biaoge"
    android:orientation="vertical"
    android:stretchColumns="0,3"
    tools:context=".MainActivity">

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="400dp">
        <TextView/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="账 号:"
            android:textSize="24sp"/>
        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="邮箱或手机号"
            android:textSize="24sp" />
        <TextView/>
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp">
        <TextView/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="密 码:"
            android:textSize="24sp"/>
        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="输入6~16位数字或字母"
            android:textSize="24sp" />
        <TextView/>
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp">
        <TextView/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="注册"
            android:layout_marginRight="10dp"
            android:textSize="20sp"
            android:background="#AA000000"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="登录"
            android:textSize="20sp"/>
        <TextView/>
    </TableRow>
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp">
        <TextView/>
        <TextView/>
        <TextView
            android:id="@+id/forgetPassword"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:text="忘记密码?"
            android:textSize="20sp"/>
        <TextView/>
    </TableRow>

</TableLayout>

(2)创建一个名为PasswordActivity的Activity,并设置它的布局文件为activity_password.xml,内容如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/beijing"
    android:orientation="vertical"
    tools:context=".PasswordActivity">

    <ImageButton
        android:id="@+id/closeButton"
        android:layout_width="75dp"
        android:layout_height="75dp"
        android:src="@mipmap/guanbi"
        android:background="#FFFFFF"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="30dp"
        android:text="你的邮箱或手机号:"
        android:textSize="20sp"/>

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="5dp"
        android:hint="请输入您的邮箱或手机号"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="5dp"
        android:text="提交"
        android:textSize="20sp"/>
</LinearLayout>

(3)在主活动MainActivity中为“忘记密码”设置setOnClickListener监听器,MainActivity.java文件内容如下:

public class MainActivity extends AppCompatActivity {
    TextView forgetPassword;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        forgetPassword = findViewById(R.id.forgetPassword);
        forgetPassword.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, PasswordActivity.class);
                startActivity(intent);
            }
        });
    }
}

(4)在活动PasswordActivity中为“关闭按钮”设置setOnClickListener监听器,PasswordActivity.java文件内容如下:

public class PasswordActivity extends AppCompatActivity {
    ImageButton closeButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_password);

        closeButton = findViewById(R.id.closeButton);
        closeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
}

在这里插入图片描述

6.3 多个Activity的使用

在Android应用中,经常会有多个Activity,而这些Activity之间又经常需要交换数据。下面就来介绍如何使用Bundle在Activity之间交换数据,以及如何调用另一个Activity并返回结果。

6.3.1 使用Bundle在Activity之间交换数据

当在一个Activity中启动另一个Activity时,经常需要传递一些数据。这时就可以通过Intent来实现,因为Intent通常被称为时两个Activity之间的信使,通过将要传递的数据保存在Intent中,可以将其传递到另一个Activity中。在Android中,可以将要保存的数据存放在Bundle对象中,然后通过Intent提供的putExtras()方法将要携带的数据保存到Intent中。

说明:Bundle是一个key-value(键-值)对的组合,用于保存要携带的数据包。这些数据可以是boolean、byte、int、long、float、double和String等基本数据类型或者对应的数组,也可以是对象或者对象数组。如果时对象或者对象数组时,必须实现Serializable或者Parcelable接口。

下面通过一个实例(模拟保存淘宝收货地址)介绍如何使用Bundel在Activity之间交换数据:

(1)主活动的布局文件activity_main.xml内容如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/investigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="fitXY"
        android:src="@mipmap/top"/>

    <EditText
        android:id="@+id/address1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/investigation"
        android:layout_marginTop="5dp"
        android:hint="所在地区"/>

    <EditText
        android:id="@+id/address2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/address1"
        android:layout_marginTop="5dp"
        android:hint="所在街道"/>

    <EditText
        android:id="@+id/address3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/address2"
        android:layout_marginTop="5dp"
        android:hint="详细地址"/>

    <EditText
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/address3"
        android:layout_marginTop="5dp"
        android:hint="收货人姓名"/>

    <EditText
        android:id="@+id/phoneNumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/name"
        android:layout_marginTop="5dp"
        android:hint="收货人手机号码"/>

    <EditText
        android:id="@+id/emailBox"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/phoneNumber"
        android:layout_marginTop="5dp"
        android:hint="邮箱"/>

    <Button
        android:id="@+id/saveButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/emailBox"
        android:layout_alignParentRight="true"
        android:layout_marginTop="20dp"
        android:text="保存"
        android:textSize="24sp"/>

</RelativeLayout>

(2)新建活动AddressActivity,并且编写器布局文件activity_address.xml文件,其文件内容如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AddressActivity">

    <ImageView
        android:id="@+id/investigation2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="fitXY"
        android:src="@mipmap/top"/>

    <TextView
        android:id="@+id/nameInfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/investigation2"
        android:layout_marginLeft="10dp"
        android:textSize="20sp"/>

    <TextView
        android:id="@+id/numberInfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/nameInfo"
        android:layout_alignParentRight="true"
        android:layout_marginRight="10dp"
        android:textSize="20sp"/>

    <TextView
        android:id="@+id/addressInfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/nameInfo"
        android:layout_alignLeft="@id/nameInfo"
        android:layout_marginTop="5dp"
        android:textSize="20sp"/>
</RelativeLayout>

(3)主活动MainActivity的文件内容如下:

public class MainActivity extends AppCompatActivity {
    Button saveButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        saveButton = findViewById(R.id.saveButton);

        saveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String address1 = ((EditText)findViewById(R.id.address1)).getText().toString();
                String address2 = ((EditText)findViewById(R.id.address2)).getText().toString();
                String address3 = ((EditText)findViewById(R.id.address3)).getText().toString();

                String name = ((EditText)findViewById(R.id.name)).getText().toString();
                String phoneNumber = ((EditText)findViewById(R.id.phoneNumber)).getText().toString();
                String emailBox = ((EditText)findViewById(R.id.emailBox)).getText().toString();

                if(!"".equals(address1) && !"".equals(address2) && !"".equals(address3)
                        && !"".equals(name) && !"".equals(phoneNumber) && !"".equals(emailBox)) {
                    //将输入的信息保存到Bundle中,通过Intent传递到另一个Activity中显示出来
                    Intent intent = new Intent(MainActivity.this, AddressActivity.class);
                    //创建并实例化一个Bundle对象
                    Bundle bundle = new Bundle();
                    bundle.putCharSequence("name", name);
                    bundle.putCharSequence("phoneNumber", phoneNumber);
                    bundle.putCharSequence("address1", address1);
                    bundle.putCharSequence("address2", address2);
                    bundle.putCharSequence("address3", address3);
                    intent.putExtras(bundle); //将Bundle对象添加到Intent对象中
                    startActivity(intent);
                }
                else {
                    //设置对话框提示信息未填写完整
                    AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).create();
                    dialog.setTitle("温馨提示"); //设置标题
                    dialog.setMessage("请将收货信息填写完整!"); //提示信息
                    dialog.setButton(DialogInterface.BUTTON_POSITIVE, "是", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    });
                    dialog.show();
                }
            }
        });
    }
}

(4)活动AddressActivity的文件内容如下:

public class AddressActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_address);

        Intent intent = getIntent();
        Bundle bundle = intent.getExtras();
        TextView name = findViewById(R.id.nameInfo);
        TextView phoneNumber = findViewById(R.id.numberInfo);
        TextView address = findViewById(R.id.addressInfo);

        name.setText(bundle.getString("name"));
        phoneNumber.setText(bundle.getString("phoneNumber"));
        address.setText(bundle.getString("address1") + bundle.getString("address2") +
                bundle.getString("address3"));
    }
}

在这里插入图片描述

在这里插入图片描述

6.3.2 调用另一个Activity并返回结果

在Android应用开发时,有时候需要在一个Activity中调用另一个Activity,当用户在第二个Activity中选择完成后,程序将自动返回到第一个Activity中,第一个Activity能够获取并显示用户在第二个Activity中的选择。例如,用户在修改信息的时候可以对头像进行修改,在修改头像时首先需要调用选择头像的界面。在选择头像后会自动返回到修改信息界面,并显示用户选择的新头像。

此功能也可以通过Intent和Bundle来实现。与两个Activity之间交换数据不同的是,此处需要使用startActivityForResult()方法来启动另一个Activity。调用startActivityForResult()方法启动Activity后,关闭新启动的Activity时,可以将选择的结果返回Activity中。startActivityForResult()方法的语法格式如下:

public void startActivityForResult(Intent intent, int requestCode)

该方法将以指定的请求码启动Activity,并且程序将会获取新启动的Activity方式的结果(通过重写onActivityResult()方法来获取)。requestCode参数代表了启动Activity的请求码,该请求码的值由开发者根据业务自行设置,用于标识请求来源。

下面通过一个实例(模拟喜马拉雅FM更换头像)进行演示:

(1)主活动布局文件activity_main.xml内容如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/beijing"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/image"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:src="@mipmap/touxiang"
        android:layout_marginTop="30dp"
        android:layout_gravity="center_horizontal"/>

    <Button
        android:id="@+id/selectButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_gravity="center_horizontal"
        android:text="选择头像"
        android:textSize="20sp"/>

</LinearLayout>

(2)活动HeadActivity的布局文件activity_head.xml内容如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".HeadActivity">

    <GridView
        android:id="@+id/gridView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        android:horizontalSpacing="3dp"
        android:verticalSpacing="3dp"
        android:numColumns="4"/>

</LinearLayout>

(3)为GridView添加OnItemClickListener事件监听器,在重写的onItemClick()方法中,首先获取Intent对象,然后创建一个要传递的数据包,并将选中的头像ID保存到该数据包中,再将要传递的数据包保存到Intent中,并设置返回的结果码及返回的Activity,最后关闭当前的Activity,HeadActivity.java内容如下:

public class HeadActivity extends AppCompatActivity {
    private int[] imageId = {
            R.mipmap.touxiang1, R.mipmap.touxiang2, R.mipmap.touxiang3,
            R.mipmap.touxiang4, R.mipmap.touxiang5
    };

    GridView gridView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_head);

        gridView = findViewById(R.id.gridView);

        BaseAdapter adapter = new BaseAdapter() {
            @Override
            public int getCount() {
                return imageId.length;
            }

            @Override
            public Object getItem(int position) {
                return position;
            }

            @Override
            public long getItemId(int position) {
                return position;
            }

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                ImageView imageView;
                if(convertView == null) {
                    imageView = new ImageView(HeadActivity.this);
                    imageView.setAdjustViewBounds(true);
                    imageView.setMaxWidth(158);
                    imageView.setMaxHeight(150);
                    imageView.setPadding(5, 5, 5, 5);
                }
                else {
                    imageView = (ImageView) convertView;
                }
                imageView.setImageResource(imageId[position]); //设置要显示的图片
                return imageView;
            }
        };
        gridView.setAdapter(adapter); //关联适配器

        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent = getIntent(); //获取intent对象
                Bundle bundle = new Bundle(); //实例化要传递的数据包
                bundle.putInt("imageId", imageId[position]); //显示选中的图片
                intent.putExtras(bundle); //将数据包保存在intent中
                setResult(0x11, intent); //设置返回的结果码,并返回调用该Activity的Activity
                finish();
            }
        });
    }
}

(4)在主活动MainActivity中重写onActivityResult()方法,在该方法中,需要判断requestCode请求码和resultCode结果码是否与预先设置的相同,如果相同,则获取传递的数据包,并从该数据宝中国获取选择的头像ID并显示,MainActivity.java内容如下:

public class MainActivity extends AppCompatActivity {
    Button selectButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        selectButton = findViewById(R.id.selectButton);
        selectButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, HeadActivity.class);
                startActivityForResult(intent, 0X11);
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == 0x11 && resultCode == 0x11) { //判断是否为待处理的结构
            Bundle bundle = data.getExtras(); //获取传递的数据包
            int imageId = bundle.getInt("imageId");
            ImageView imageView = findViewById(R.id.image);
            imageView.setImageResource(imageId); //显示选择的头像
        }
    }
}

在这里插入图片描述

在这里插入图片描述

6.4 使用Fragment

Fragment是Android 3.0新增的概念,其中文意思是碎片,它与Activity十分相似,用来在一个Activity中描述一些行为或一部分用户界面。使用多个Fragment可以在一个单独的Activity中建立多个UI面板,也可以在多个Activity中重用Fragment。例如,微信主界面就相当于一个Activity,在这个Activity中包含多个Fragment,其中“微信”,“通讯录”,“发现”,“我”这4个功能界面,每一个功能界面就相当于一个Fragment,它们之间可以随意切换。

6.4.1 Fragment的生命周期

和Activity一样,Fragment也有自己的生命周期。一个Fragment必须被嵌入一个Activity中,它的生命周期直接受其所属的宿主Activity的生命周期影响。例如,当Activity被暂停时,其中的所有Fragment也被暂停;当Activity被销毁时,所有隶属于它的Fragment也将被销毁。然而,当一个Activity正在运行时(处于resumed状态),我们可以单独地对每一个Fragment进行操作,如添加或删除等。Fragment的完整生命周期如下图所示:

在这里插入图片描述

6.4.2 创建Fragment

要创建一个Fragment,必须创建一个Fragment的子类,或者继承自另一个已经存在的Fragment的子类。例如,要创建一个名称为NewsFragment的Fragment,并重写onCreateView()方法,可以使用下面的代码:

public class NewsFragment extends Fragment {
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		//从布局文件news.xml加载一个布局文件
		View v = inflater.inflate(R.layout.news, container, false);
	}
}

说明:当系统首次调用Fragment时,如果想绘制一个UI界面,那么在Fragment中,必须重写onCreateView()方法返回一个View;如果Fragment没有UI界面,可以返回null。

6.4.3 在Activity中添加Fragment

向Activity中添加Fragment有两种方法:一种是直接在布局文件中添加,将Fragment作为Activity整个布局的一部分;另一部分是当Activity运行时,将Fragment放入Activity布局中。下面分别进行介绍。

1. 直接在布局文件中添加Fragment

直接在布局文件中添加Fragment可以使用<fragment></fragment>标记实现。例如,要在一个布局文件中添加两个Fragment,可以使用下面的代码:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <fragment android:name="com.example.ListFragment"
        android:id="@+id/list"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="match_parent"/>

    <fragment android:name="com.example.DetailFragment"
        android:id="@+id/detail"
        android:layout_weight="2"
        android:layout_width="0dp"
        android:layout_height="match_parent"/>
</LinearLayout>

说明:在<fragment></fragment>标记中,android:name属性用于指定要添加的Fragment。

2. 当Activity运行时添加Fragment

当Activity运行时,也可以将Fragment添加到Activity的布局中,实现方法是获取一个FragmentTransaction的实例,然后使用add()方法添加一个Fragment,add()方法的第一个参数是Fragment要放入的ViewGroup(由Resource ID),第二个参数是需要添加的Fragment,最后为了使改变生效,还必须调用commit()方法提交事务。例如,要在Activity运行时添加一个名称为DetailFragment的Fragment,还可以使用下面的代码:

DetailFragment details = new DetailFragment(); //实例化一个DetailFragment的对象
FragmentTransaction ft = getFragmentManager().beginTransaction(); //获取一个FragmentTransaction的实例
ft.add(android.R.id.content, details); //添加一个显示详细内容放入Fragment
ft.commit(); //提交事务

Fragment比较强大的功能之一就是可以合并两个Activity,从而让这两个Activity在一个屏幕上显示。如下图所示,左边的两个图分别代表两个Activity,右边的图表示包括两个Fragment的Activity,其中第一个Fragment的内容是Activity A,第二个Fragment的内容是Activity B。

在这里插入图片描述

下面通过一个实例(模拟微信切换界面)介绍在Fragment在App中的实际应用:

(1)修改新建的Module的res\layout目录下的布局文件activitt_main.xml,添加一个Fragment组件,并为其设置ID,在Fragment组件下面添加一个水平线性布局管理器,并设置其显示在容器底部,最后在水平线性布局管理器中添加4个布局宽度的ImageView,将它们的layout_weight属性设置为1,具体内容如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/fragment"
        android:name="com.example.wechatinterfacechange.WeChat_Fragement"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="61dp"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/image1"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="61dp"
            android:src="@mipmap/bottom_1"/>

        <ImageView
            android:id="@+id/image2"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="61dp"
            android:src="@mipmap/bottom_2"/>

        <ImageView
            android:id="@+id/image3"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="61dp"
            android:src="@mipmap/bottom_3"/>

        <ImageView
            android:id="@+id/image4"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="61dp"
            android:src="@mipmap/bottom_4"/>
    </LinearLayout>

</RelativeLayout>

(2)在res\layout目录下创建一个名称为wechat_fragment.xml的布局文件,并且将默认创建的线性布局布局管理器改为相对布局管理器,然后在该局部文件中添加一个ImageView组件,用户存放要显示的图片,具体内容如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/weixin"
        android:scaleType="fitXY"/>

</RelativeLayout>

(3)在工具窗口中的WeChat Interface Change\java节点的第一个com.example包中创建一个名称为WeChat_Fragment的类,让这个类继承Fragment,并且重写onCreateView()方法,然后为WeChatFragment添加wechat_fragment.xml布局文件,具体内容如下:

public class WeChat_Fragement extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.wechat_fragment, null);
        return view;
    }
}

(4)按照步骤(2)、(3)的方法,再创建3个Fragement类和3个对应的布局文件,分别用于实现“通讯录”、“发现”、“我”3个界面

(5)打开默认的创建的MainActivity,获取布局文件中的4张Tab标签图片,并且为每一个图片设置单击事件监听器,并创建相应的Fragement替换原有的Fragement,具体内容如下:

public class MainActivity extends AppCompatActivity {
    private ImageView imageView1, imageView2, imageView3, imageView4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView1 = findViewById(R.id.image1);
        imageView2 = findViewById(R.id.image2);
        imageView3 = findViewById(R.id.image3);
        imageView4 = findViewById(R.id.image4);

        imageView1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentTransaction ft = getFragmentManager().beginTransaction();
                Fragment f  = new WeChat_Fragement();
                ft.replace(R.id.fragment, f); //替换Fragment
                ft.commit(); //提交事务
            }
        });
        imageView2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentTransaction ft = getFragmentManager().beginTransaction();
                Fragment f  = new Message_Fragment();
                ft.replace(R.id.fragment, f); //替换Fragment
                ft.commit(); //提交事务
            }
        });
        imageView3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentTransaction ft = getFragmentManager().beginTransaction();
                Fragment f  = new Find_Fragment();
                ft.replace(R.id.fragment, f); //替换Fragment
                ft.commit(); //提交事务

            }
        });
        imageView4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentTransaction ft = getFragmentManager().beginTransaction();
                Fragment f  = new Me_Fragment();
                ft.replace(R.id.fragment, f); //替换Fragment
                ft.commit(); //提交事务
            }
        });
    }
}

在这里插入图片描述

  • 12
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值