概述
Fragment
表示 FragmentActivity
中的行为或界面的一部分。您可以在一个Activity
中组合多个片段,从而构建多窗格界面,并在多个Activity
中重复使用某个片段。您可以将片段视为 Activity
的模块化组成部分,它具有自己的生命周期,能接收自己的输入事件,并且您可以在Activity
运行时添加或移除片段(这有点像可以在不同Activity
中重复使用的“子 Activity
”)。
片段必须始终托管在 Activity
中,其生命周期直接受宿主 Activity
生命周期的影响。例如,当 Activity
暂停时,Activity
的所有片段也会暂停;当Activity
被销毁时,所有片段也会被销毁。不过,当 Activity
正在运行(处于已恢复生命周期状态)时,您可以独立操纵每个片段,如添加或移除片段。当执行此类片段事务时,您也可将其添加到由 Activity
管理的返回栈 —Activity
中的每个返回栈条目都是一条已发生片段事务的记录。借助返回栈,用户可以通过按返回按钮撤消片段事务(后退)。
当您将片段作为 Activity
布局的一部分添加时,其位于 Activity
视图层次结构的某个 ViewGroup
中,并且片段会定义其自己的视图布局。您可以通过在 Activity
的布局文件中声明片段,将其作为<fragment>
元素插入您的 Activity
布局,或者通过将其添加到某个现有的ViewGroup
,利用应用代码将其插入布局。
本文介绍如何在开发应用时使用片段,包括如何在将片段添加到 Activity
返回栈时保持其状态、如何与 Activity
及 Activity
中的其他片段共享事件、如何为 Activity
的应用栏发挥作用等等。
Fragment
类的代码与Activity
非常相似。它包含与Activity
类似的回调方法,如 onCreate()
、onStart()
、onPause()
和 onStop()
。实际上,如果您要将现有Android
应用转换为使用片段,可能只需将代码从Activity
的回调方法移入片段相应的回调方法中。
通常,您至少应实现以下生命周期方法:
onCreate()
系统会在创建片段时调用此方法。当片段经历暂停或停止状态继而恢复后,如果您希望保留此片段的基本组件,则应在您的实现中将其初始化。onCreateView()
系统会在片段首次绘制其界面时调用此方法。如要为您的片段绘制界面,您从此方法中返回的 View 必须是片段布局的根视图。如果片段未提供界面,您可以返回 null。onPause()
系统会将此方法作为用户离开片段的第一个信号(但并不总是意味着此片段会被销毁)进行调用。通常,您应在此方法内确认在当前用户会话结束后仍然有效的任何更改(因为用户可能不会返回)。
大多数应用至少应为每个片段实现这三个方法, 但您还应使用几种其他回调方法来处理片段生命周期的各个阶段。处理片段生命周期部分对所有生命周期回调方法做了更详尽的阐述。
举例说明
创建二个碎片布局
片段通常用作 Activity
界面的一部分,并且会将其自己的布局融入Activity。
如要为片段提供布局,您必须实现 onCreateView()
回调方法,Android
系统会在片段需要绘制其布局时调用该方法。此方法的实现所返回的View
必须是片段布局的根视图。
如要从onCreateView()
返回布局,您可以通过XML
中定义的布局资源来扩展布局。为帮助您执行此操作,onCreateView()
提供了一个LayoutInflater
对象。
传递至onCreateView()
的container
参数是您的片段布局将插入到的父级ViewGroup
(来自 Activity 的布局)。savedInstanceState
参数是在恢复片段时,提供上一片段实例相关数据的Bundle
(处理片段生命周期部分对恢复状态做了详细阐述)。
inflate()
方法带有三个参数:
- 您想要扩展的布局的资源 ID。
将作为扩展布局父项的 ViewGroup。传递 container 对系统向扩展布局的根视图(由其所属的父视图指定)应用布局参数具有重要意义。 - 指示是否应在扩展期间将扩展布局附加至 ViewGroup(第二个参数)的布尔值。(在本例中,此值为 false,因为系统已将扩展布局插入 container,而传递 true 值会在最终布局中创建一个多余的视图组。)
现在,您已了解如何创建提供布局的片段。接下来,您需将该片段添加到您的 Activity 中。 - 第一个碎片布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="#00ff00"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/left_button"
android:text="@string/left_button"
tools:ignore="HardcodedText"
/>
</LinearLayout>
- 第二个碎片布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="#0000ff"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/right_button"
android:text="@string/right_gragment"
/>
</LinearLayout>
可以看到和普通的布局文件是一样的。
创建二格碎片类
创建二个java类继承Fragment
,用于产生碎片类。
如要为片段提供布局,您必须实现 onCreateView()
回调方法,Android
系统会在片段需要绘制其布局时调用该方法。此方法的实现所返回的 View 必须是片段布局的根视图。
如要从 onCreateView()
返回布局,您可以通过 XML
中定义的布局资源来扩展布局。为帮助您执行此操作,onCreateView()
提供了一个 LayoutInflater 对象。
- 碎片一
package cn.onesb.fragmenttest;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class Left_fragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_fragment, container, false);
return view;
}
}
- 碎片2
package cn.onesb.fragmenttest;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class Right_fragment extends Fragment {
private String TAG = this.getClass().getSimpleName();
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate:碎片被创建 ");
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.right_fragment, container, false);
return view;
}
}
在活动布局中加载二个碎片布局
在
android:name
属性中写上实例化的fragment类全路径
比如:android:name="cn.onesb.fragmenttest.Left_fragment"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android:name="cn.onesb.fragmenttest.Left_fragment"
android:id="@+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment android:name="cn.onesb.fragmenttest.Right_fragment"
android:id="@+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
试运行
- 布局文件
- 点击按钮