☰
android-training-course-in-chinese:Fragment 创建与集成实战指南
2026/10/5 6:49:44 网站建设 项目流程
  • 文档
  • 教程
  • 移动开发

【免费下载链接】android-training-course-in-chinese

Android官方培训课程中文版

项目地址:https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese
点击查看免费下载

本文基于 android-training-course-in-chinese 仓库中 basics/fragments/creating.md 课程,结合同章节的 fragment-ui.md、communicating.md 以及仓库内 Action Bar、多屏幕适配等关联资料,系统讲解如何创建 Fragment、将其集成进 Activity,并在低版本 Android 上保持兼容。

导读

Fragment 是 Android 中可复用的模块化 UI 组件,可以把它想象成"Activity 的模块":它拥有自己的生命周期,能够接收输入事件,可以在 Activity 运行过程中被添加或移除,并且能在不同 Activity 中重复使用。本指南将教你创建第一个 Fragment 类、通过 XML 布局将其声明式地嵌入 Activity,并解决低版本 Android(最低至 1.6)的兼容性问题。读完本文,你将掌握 Fragment 类编写、布局资源组织、FragmentActivity/AppCompatActivity的正确选型,以及"XML 静态声明"与"运行时动态事务"两种集成方式的差异与取舍。

一、课前准备:引入 Support Library

Fragment 自 Android 3.0(API level 11)起才作为平台 API 加入。为了让应用在 Android 1.6 这样的低版本上也能使用 Fragment,必须引入 Support Library:

  • 最基础的做法是使用v4支持库,其中包含了android.support.v4.app.Fragment、android.support.v4.app.FragmentActivity等一系列关键类;
  • 也可以直接使用包含APP Bar能力的v7 appcompat库。该库兼容 Android 2.1(API level 7),同时也完整包含了 Fragment API,并额外提供了AppCompatActivity与Theme.AppCompat主题体系。

仓库中 basics/actionbar/setting-up.md 给出了 v7 appcompat 的接入要点:引入库之后,Activity 改为继承ActionBarActivity(即后来AppCompatActivity的前身),并在 Manifest 中为<application>或<activity>指定Theme.AppCompat(或其子类如Theme.AppCompat.Light)主题,同时将minSdkVersion设置为7、targetSdkVersion按需设置,即可让应用在 Android 2.1 及以上版本拥有 Action Bar 与 Fragment 能力。

二、创建 Fragment 类

创建 Fragment 的第一步是从Fragment继承并编写自己的子类,然后在关键生命周期方法中插入代码——处理方式与 Activity 完全一致。

2.1 唯一的必需回调:onCreateView()

创建 Fragment 时,必须重写onCreateView()回调方法来定义布局。事实上,这是为了让一个 Fragment 运行起来唯一需要重写的回调方法。onCreateView()负责为 Fragment 填充布局,其返回值是 Fragment 对应的根View。

下面是一个自定义布局的 Fragment 示例(对应原文档中的ArticleFragment):

import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.ViewGroup; public class ArticleFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // 拉伸该 Fragment 的布局 return inflater.inflate(R.layout.article_view, container, false); } }

这里的要点:

  • inflater.inflate(R.layout.article_view, container, false)第三个参数为false,表示不将填充结果自动挂载到container上。Fragment 的视图最终由 FragmentManager 负责挂载,若此处传入true会造成视图重复添加;
  • container是 Activity 布局中用于承载该 Fragment 的父容器(ViewGroup),系统会在合适时机将其作为onCreateView的参数传入;
  • savedInstanceState用于在重建时恢复 Fragment 的保存状态,与 Activity 的机制类似。

2.2 生命周期与 Activity 同步

和 Activity 一样,当 Fragment 从 Activity 添加或移除、或 Activity 生命周期发生变化时,Fragment 通过生命周期回调方法管理自身状态。关键规律是:Fragment 的生命周期与宿主 Activity 绑定。例如,当 Activity 的onPause()被调用时,其内部所有 Fragment 的onPause()方法也会被触发。

关于 Fragment 完整的生命周期与回调方法清单,可进一步参考仓库中 basics/fragments/index.md 课程的后续内容(onStart、onResume、onStop、onDestroyView、onDetach等),其中onDestroyView用于释放 Fragment 视图相关资源,onDetach在 Fragment 与 Activity 解除关联时调用。

三、用 XML 将 Fragment 添加到 Activity

Fragment 是可重用、模块化的 UI 组件。每个 Fragment 实例都必须与一个FragmentActivity关联。最直接的关联方式,就是在 Activity 的 XML 布局文件中用<fragment>标签逐个声明 Fragment。

兼容性注记:FragmentActivity是 Support Library 提供的特殊 Activity 基类,专门用于在 API level 11 以下的系统上承载 Fragment。如果你的应用minSdkVersion >= 11,可以直接使用普通的Activity(平台原生的 Fragment 支持自 11 起可用)。

3.1 为不同屏幕准备不同布局

原文档展示了一个典型场景:当屏幕被判定为 "large"(通过布局目录名称中的large限定符区分)时,在布局中同时放置两个 Fragment,形成左右并排的双窗格界面:

res/layout-large/news_articles.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <fragment android:name="com.example.android.fragments.HeadlinesFragment" android:id="@+id/headlines_fragment" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <fragment android:name="com.example.android.fragments.ArticleFragment" android:id="@+id/article_fragment" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout>

布局要点:

  • <fragment>标签的android:name属性必须填写Fragment 类的完整限定名(包名 + 类名),系统据此实例化对应的 Fragment;
  • android:id用于之后通过findFragmentById()定位该 Fragment;
  • 两个 Fragment 分别设置layout_weight为 1 和 2、宽度为0dp,从而按 1:2 的比例均分横向空间(新闻列表占 1/3,文章正文占 2/3);
  • layout-large目录限定符保证该双窗格布局只在大屏设备上生效。

仓库中 ui/multiscreen/screen-sizes.md 对"尺寸限定词"机制有更系统的讲解:除了large,还可以使用sw600dp等最小宽度限定符,在运行时根据设备配置选择最合适的布局资源。同目录还展示了新闻阅读器示例中在单个布局里直接声明<fragment>(com.example.android.newsreader.HeadlinesFragment)的用法。

3.2 在 Activity 中加载该布局

将这个布局文件应用到 Activity 中。使用 v4 支持库时,Activity 必须继承自FragmentActivity:

import android.os.Bundle; import android.support.v4.app.FragmentActivity; public class MainActivity extends FragmentActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.news_articles); } }

如果使用的是v7 appcompat 库,则 Activity 应改为继承自AppCompatActivity——它是FragmentActivity的子类,在保留全部 Fragment 能力的同时额外提供 Action Bar / App Bar 支持(仓库 basics/actionbar/setting-up.md 详细介绍了配套的Theme.AppCompat主题与 Manifest 配置)。

3.3 静态声明的限制

重要限制:当通过 XML 布局文件的方式(<fragment>标签)将 Fragment 添加进 Activity 时,该 Fragment 不能被动态移除。如果你需要在用户交互时把 Fragment 切入切出,就必须在 Activity 启动之后、通过代码运行时添加 Fragment。这部分内容正是同章节 basics/fragments/fragment-ui.md 的主题。

四、进阶:运行时动态添加与替换 Fragment

虽然 XML 静态声明简单直接,但它不具备动态性。要实现"在手机上一次只显示一个 Fragment、通过导航切换"这类体验,必须使用 FragmentManager + FragmentTransaction 在运行时操作 Fragment。示意图(basics/fragments/fragments-screen-mock.png)清晰地展示了同一 Activity 在不同尺寸屏幕上的两种配置:平板上两个 Fragment 并列显示,手机上则依次单窗格展示。

图1:两个 Fragment 在不同尺寸屏幕上的布局配置——大屏并列显示,小屏依次切换

4.1 准备容器:FrameLayout

运行时添加 Fragment 时,必须在 Activity 布局中提供一个作为容器的View。典型的做法是用一个空的FrameLayout作为占位容器。下面这个布局文件与 3.1 节的文件同名(news_articles.xml),但放在不带large限定符的普通layout目录下,因此会在屏幕小于 "large" 的设备上被选用:

res/layout/news_articles.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" />

4.2 在 onCreate() 中添加初始 Fragment

添加或移除 Fragment 的事务通过FragmentManager创建FragmentTransaction完成。流程为:调用getSupportFragmentManager()获取 FragmentManager → 调用beginTransaction()创建事务 → 调用add()添加 Fragment → 调用commit()提交。同一个FragmentTransaction可以承载多个 Fragment 操作。

import android.os.Bundle; import android.support.v4.app.FragmentActivity; public class MainActivity extends FragmentActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.news_articles); // 确认 Activity 使用的布局版本包含 fragment_container FrameLayout if (findViewById(R.id.fragment_container) != null) { // 如果要从先前的状态还原,则直接返回,否则会得到重叠的 Fragment if (savedInstanceState != null) { return; } // 创建一个要放入 Activity 布局中的新 Fragment HeadlinesFragment firstFragment = new HeadlinesFragment(); // 如果此 Activity 是通过 Intent 发出的特殊指令启动的, // 将 Intent 的 extras 以参数形式传递给该 Fragment firstFragment.setArguments(getIntent().getExtras()); // 将该 Fragment 添加到 "fragment_container" FrameLayout 中 getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, firstFragment).commit(); } } }

这段代码中值得注意的细节:

  • findViewById(R.id.fragment_container) != null用于区分当前使用的是双窗格布局还是单窗格布局,是"同一 Activity 适配多屏"的惯用手法;
  • savedInstanceState != null时直接return,避免系统在旋转重建时把 Fragment 重复添加;
  • setArguments()传参方式优于直接调用 Fragment 的 setter 方法:参数随 Fragment 一起被系统保存和恢复,是官方推荐的数据传递方式(配合onCreate/onCreateView中的getArguments()读取)。

4.3 替换 Fragment 与返回栈

替换 Fragment 与添加步骤相似,只是把add()换成replace()。在执行替换或移除等事务时,为了让用户能够向后导航并"撤消"更改,需要调用addToBackStack()后再提交事务:

// 创建 Fragment 并添加参数,指定应显示的文章 ArticleFragment newFragment = new ArticleFragment(); Bundle args = new Bundle(); args.putInt(ArticleFragment.ARG_POSITION, position); newFragment.setArguments(args); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // 将 fragment_container 中的内容替换为此 Fragment, // 然后将该事务添加到返回栈,以便用户可以向后导航 transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); // 执行事务 transaction.commit();

关于返回栈,原文档给出了一条关键的行为差异:

注:当你移除或替换 Fragment 并向返回栈添加事务时,被移除的 Fragment 会停止(stop)而不是销毁。用户向后导航还原该 Fragment 时,它会重新启动;如果你没有向返回栈添加事务,那么该 Fragment 在移除或替换时就会被销毁。

addToBackStack()还可接收一个可选的字符串参数为事务命名,供FragmentManager.BackStackEntryAPI 进行高级操作时使用;普通场景传null即可。

五、配套实践:Fragment 与 Activity 的交互

Fragment 的价值在于复用与模块化。为保证每个 Fragment 完全自包含,所有 Fragment 之间的交互都应通过宿主 Activity 完成,两个 Fragment 不应直接通信。仓库中 basics/fragments/communicating.md 给出了标准的"接口回调"模式,与本文创建的HeadlinesFragment/ArticleFragment示例一脉相承:

  1. Fragment 定义接口并在 onAttach() 中获取实现——在onAttach(Activity)中将宿主 Activity 强转为接口类型,失败则抛出ClassCastException,实现"容器必须实现该接口"的契约校验;
  2. Activity 实现接口接收回调——例如MainActivity implements HeadlinesFragment.OnHeadlineSelectedListener,在onArticleSelected(int position)中响应点击事件;
  3. Activity 通过findFragmentById()找到目标 Fragment 并直接调用其 public 方法——如果拿到的是双窗格布局中的现有 Fragment 就直接更新;否则新建 Fragment、setArguments传参、replace()+addToBackStack()完成单窗格切换。这与 4.3 节的替换代码完全一致,形成了"创建 → 静态/动态集成 → 交互"的完整闭环。

六、小结:两种集成方式的选型对照

对比维度XML 静态声明(<fragment>标签)运行时事务(FragmentManager)
定义位置Activity 布局文件中Java 代码中
是否可动态移除/替换不可可以
典型场景大屏双窗格固定布局手机单窗格切换、动态 UI
关键 APIsetContentView(R.layout.news_articles)getSupportFragmentManager().beginTransaction().add()/replace()...commit()
兼容前提FragmentActivity(v4)或AppCompatActivity(v7)同上

本课所学的 Fragment 创建、XML 集成与生命周期知识,是后续"构建有弹性的 UI(fragment-ui.md)"与"与其他 Fragment 交互(communicating.md)"两课的基础。掌握"静态声明 + 动态事务 + 接口回调"这套组合拳,你就能用同一套 Fragment 代码为手机与平板提供差异化的自适应体验。

  • 文档
  • 教程
  • 移动开发

【免费下载链接】android-training-course-in-chinese

Android官方培训课程中文版

项目地址:https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese
点击查看免费下载
上一篇:SmartSystemMenu 点击穿透使用指南:3 步让窗口"看得见、点不到"
下一篇:AI红队研究方向全景:从可扩展漏洞发现到可证明安全保证的五大课题与实践路径

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询