Android Kotlin 基础知识:创建 fragment

此 Codelab 是“Android Kotlin 基础知识”课程的一部分。如果您按顺序学习这些 Codelab,您将会充分发掘此课程的价值。“Android Kotlin 基础知识”Codelab 着陆页列出了所有课程 Codelab。

在此 Codelab 中,您将学习 fragment,它表示 activity 中界面的一种行为或某一部分。您需要在一个名为 AndroidTrivia 的有趣起始应用中创建一个 fragment。在下一个 Codelab 中,您将详细学习导航,并进一步开发 AndroidTrivia 应用。

您应当已掌握的内容

  • Kotlin 的基础知识
  • 如何使用 Kotlin 创建基本 Android 应用
  • 如何使用布局

学习内容

  • 如何向应用静态添加 fragment

实践内容

  • 在 activity 内创建 fragment。

在构成本课程的三个 Codelab 中,相关操作是在一个名为 AndroidTrivia 的应用中完成的。这个已完成的应用是一款游戏,用户需要在游戏中回答三个有关 Android 编码的知识问答题。如果用户正确回答了所有三个问题,就会赢得游戏并且可以分享游戏结果。

AndroidTrivia 应用旨在用于介绍导航模式和控件。该应用包含以下几个组件:

  • 如上方左侧屏幕截图所示,在游戏名屏幕中,用户开始游戏。
  • 如上方中间屏幕截图所示,在显示问答题的游戏屏幕中,用户参与游戏并提交答案。
  • 如上方右侧屏幕截图所示,抽屉式导航栏从应用侧面滑出,其中包含一个带有标题的菜单。抽屉式导航栏图标 7277f85db3a1ad13.png 可用于打开抽屉式导航栏。抽屉式导航栏菜单包含一个指向“About”页面的链接和一个指向游戏规则的链接。

应用的顶部显示一个名为 *应用栏(*或操作栏)的视图,用于显示应用的名称。

在此 Codelab 中,您将使用一个初始应用,该应用提供了完成 Trivia 应用所需的模板代码和 fragment 类。

  1. 下载 AndroidTrivia-Starter Android Studio 项目。您可能需要下载整个 android-kotlin-basic-starter-apps ZIP 文件。
  2. 在 Android Studio 中打开项目并运行应用。当应用打开时,除了显示应用名称和空白屏幕,不执行任何其他操作。

ba13edd83b87b060.png

  1. 在 Android Studio 的“Project”窗格中,打开“Project: Android”视图以浏览项目文件。打开 app > java 文件夹,查看 MainActivity 类和 fragment 类。

cc34503baa186b84.png

  1. 打开 res > layout 文件夹,然后双击 activity_main.xmlactivity_main.xml 文件会显示在布局编辑器中。
  2. 打开 Design 标签页。activity_main.xml 文件对应的 Component Tree 将根布局显示为垂直 LinearLayout

19fdd9df909dfebe.png

在垂直线性布局中,布局中的所有子视图均垂直对齐。

Fragment 表示 Activity 中界面的一种行为或某一部分。您可以将多个 fragment 组合在一个 activity 中来构建多窗格界面,也可以在多个 activity 中重复使用一个 Fragment

可以将 Fragment 视为 activity 的一个模块化部分,就像您也可以在其他 activity 中使用的子 activity 一样:

  • Fragment 有自己的生命周期,会接收自己的输入事件。
  • 您可以在 activity 运行期间添加或移除 Fragment
  • Fragment 在 Kotlin 类中定义。
  • fragment 的界面在 XML 布局文件中定义。

AndroidTrivia 应用有一个主 activity 和几个 fragment。大部分 fragment 及其布局文件均已为您预先定义。在此任务中,您需要创建一个 fragment,并将 fragment 添加到应用的主 activity 中。

第 1 步:添加 fragment 类

在此步骤中,您需要创建一个空白 TitleFragment 类。首先,为新 fragment 创建一个 Kotlin 类:

  1. 在 Android Studio 中,点击“Project”窗格内的任意位置,使焦点返回到项目文件中。例如,点击 com.example.android.navigation 文件夹。
  2. 依次选择 File > New > Fragment > Fragment (Blank)
  3. 对于 fragment 名称,请输入 TitleFragment
  4. 对于 fragment 布局名称,请输入 placeholder_layout(我们不会对应用使用该布局,因为它已有为 TitleFragment 设计的布局)。
  5. 对于源语言,请选择 Kotlin
  6. 点击 Finish
  7. 打开 TitleFragment.kt fragment 文件(如果尚未打开)。它包含 onCreateView() 方法,这是在 fragment 的生命周期中调用的方法之一。
  8. 删除 onCreateView() 内的代码。onCreateView() 函数只保留以下代码:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                         savedInstanceState: Bundle?): View? {
}
  1. TitleFragment 类中,删除 onCreate() 方法、fragment 初始化参数和伴生对象。确保您的 TitleFragment 类如下所示:
class TitleFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

    }
}

创建绑定对象

fragment 目前无法编译。为了进行 fragment 编译,您需要创建一个绑定对象并膨胀 fragment 的视图(等同于对 activity 使用 setContentView())。

  1. TitleFragment.ktonCreateView() 方法中,创建一个 binding 变量 (val binding)。
  2. 如需膨胀 fragment 的视图,请对 fragment 的 Binding 对象(即 FragmentTitleBinding)调用 DataBindingUtil.inflate() 方法。

将四个参数传递到 DataBindingUtil.inflate 方法:

  • inflater,用于膨胀绑定布局的 LayoutInflater
  • 要膨胀的布局的 XML 布局资源。请使用已为您预先定义的布局之一 R.layout.fragment_title
  • 用于父级 ViewGroupcontainer。(此参数是可选的。)
  • 用于 attachToParent 值的 false
  1. DataBindingUtil.inflate 返回的绑定分配给 binding 变量。
  2. 从包含膨胀视图的方法中返回 binding.root。您的 onCreateView() 方法现在类似于以下代码:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                         savedInstanceState: Bundle?): View? {
   val binding = DataBindingUtil.inflate<FragmentTitleBinding>(inflater,
           R.layout.fragment_title,container,false)
   return binding.root
   }
  1. 打开 res>layout 并删除 placeholder_layout.xml

第 2 步:将新的 fragment 添加到主布局文件

在此步骤中,您需要将 TitleFragment 添加到应用的 activity_main.xml 布局文件中。

  1. 依次打开 res > layout > activity_main.xml,然后选择 Code 标签页,以查看布局 XML 代码。
  2. 在现有 LinearLayout 元素内,添加 fragment 元素。
  3. 将 fragment 的 ID 设置为 titleFragment
  4. 将 fragment 的名称设置为 fragment 类的完整路径,在本例中为 com.example.android.navigation.TitleFragment
  5. 将布局宽度和高度设置为 match_parent
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <fragment
                android:id="@+id/titleFragment"
                android:name="com.example.android.navigation.TitleFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                />
        </LinearLayout>

</layout>
  1. 运行应用。fragment 已添加到主屏幕。

c50adaea142a7589.png

Android Studio 项目:AndroidTriviaFragment

提醒:确保使用最新版本的 fragment (androidx.fragment.app.Fragment)。旧版本的 fragment 在 API 级别 28 中已弃用。

在此 Codelab 中,您向 AndroidTrivia 应用添加了一个 fragment,在本课的后续两个 Codelab 中您将继续在此应用中执行操作。

  • fragment 是 activity 的模块化部分。
  • fragment 有自己的生命周期,会接收自己的输入事件。
  • 使用 <fragment> 标签在 XML 布局文件中为 fragment 定义布局。
  • 膨胀 onCreateView() 中 fragment 的布局。
  • 您可以在 activity 运行期间添加或移除 fragment。

Udacity 课程:

Android 开发者文档:

此部分列出了在由教师指导的课程教学中,学生完成此 Codelab 后可能需要做的家庭作业。教师自行决定是否执行以下措施:

  • 根据需要布置作业。
  • 告知学生如何提交家庭作业。
  • 给家庭作业评分。

教师可以酌情采用这些建议,并且可以自由布置自己认为合适的任何其他家庭作业。

如果您是在自学此 Codelab,可随时通过这些家庭作业来检测您的知识掌握情况。

回答以下问题

问题 1

fragment 和 activity 之间有哪些区别?请选择所有正确的表述。

  • 创建 fragment 时,您需要在 onCreateView() 方法中膨胀布局。创建 activity 时,您需要在 onCreate() 中膨胀布局。
  • activity 有自己的布局,但 fragment 不能有自己的布局。
  • activity 有自己的生命周期,但 fragment 没有。
  • 为 fragment 或 activity 膨胀布局时,您可以用 R.layout.layoutname 的形式引用布局。

问题 2

以下关于 fragment 的表述中哪些是正确的?请选择所有适用的选项。

  • 您可以在多个 activity 中使用同一个 fragment。
  • 一个 activity 可以有多个 fragment。
  • 在 Kotlin 类中定义 fragment 后,系统会自动将 fragment 添加到 activity_main.xml 布局文件中。
  • 使用 <fragment> 标签来定义布局文件中要插入 fragment 的位置。

开始学习下一课:定义导航路径

如需本课程中其他 Codelab 的链接,请参阅“Android Kotlin 基础知识”Codelab 着陆页