创建 fragment
在此 Codelab 中,您向 AndroidTrivia 应用添加了一个 fragment,在本课的后续两个 Codelab 中您将继续在此应用中执行操作。
- fragment 是 activity 的模块化部分。
- fragment 有自己的生命周期,会接收自己的输入事件。
- 使用
<fragment>
标签在 XML 布局文件中为 fragment 定义布局。 - 膨胀
onCreateView()
中 fragment 的布局。 - 您可以在 activity 运行期间添加或移除 fragment。
定义导航路径
导航组件
如需使用 Android 导航库,您需要执行一些设置:
-
在模块级
build.gradle
文件中为navigation-fragment-ktx
和navigation-ui-ktx
添加依赖项。 -
在项目级
build.gradle
文件中为navigationVersion
添加ext
变量。
导航目的地是指用户导航到的 fragment、activity 或其他应用组件。导航图定义了从一个导航目的地到下一个导航目的地的可能路径。 -
如需创建导航图,请创建一个类型为
Navigation
的新 Android 资源文件。该文件定义了应用中的导航流。该文件位于res/navigation
文件夹中,通常名为navigation.xml
。 -
如需在 Navigation Editor 中查看导航图,请打开
navigation.xml
文件,然后点击Design
标签页。 -
您可以使用 Navigation Editor 向导航图中添加目的地,如 fragment。
-
如需定义从一个目的地到另一个目的地的路径,请使用导航图创建连接这两个目的地的操作。在
navigation.xml
文件中,每个连接都表示为具有ID
的action
。
导航宿主 fragment 通常名为 NavHostFragment,它充当导航图中 fragment 的宿主:
- 当用户在导航图中定义的目的地之间移动时,
NavHostFragment
会换入或换出 fragment 并管理 fragment 返回堆栈。 - 在
activity_main.xml
布局文件中,NavHostFragment
由名为android:name="androidx.navigation.fragment.NavHostFragment"
的fragment
元素表示。
如需定义当用户点按某个视图(例如按钮)时要显示哪个 fragment,请为该视图设置 onClick 监听器:
- 在
onClick
监听器中,对视图调用findNavController().navigate()
。 - 指定通向目的地的
action
的ID
。
条件导航是指在一种情况下导航到一个屏幕,而在另一种情况下导航到另一个屏幕。如需创建条件导航,请执行以下操作:
- 使用 Navigation Editor 从起始 fragment 到每个可能的目的地 fragment 创建一个连接。
- 为每个连接指定唯一的 ID。
- 在
View
的点击监听器方法中,添加相应的代码以检测条件。然后,对视图调用findNavController().navigate()
,并传入相应操作的 ID。
返回按钮
系统的返回按钮通常位于设备的底部。默认情况下,用户按返回按钮后会导航回他们最近查看的屏幕。在某些情况下,您可以控制用户按返回按钮后会转到何处:
- 在 Navigation Editor 中,您可以使用
Attributes
窗格来更改操作的popUpTo
设置。此设置会从返回堆栈中移除目的地,其作用是确定用户按返回按钮后会转到何处。 - 在
navigation.xml
文件中,popUpTo
设置显示为popUpTo
属性。
- 选中
popUpToInclusive
复选框时,会将popUpToInclusive
属性设置为true
。系统会从返回堆栈中移除直到并包括此目的地在内的所有目的地。 - 如果操作的
popUpTo
属性设置为应用的起始目的地且popUpToInclusive
设置为true
,则用户按返回按钮后会直接退出应用。
向上按钮
Android 应用中的屏幕可以有屏幕上的向上按钮,该按钮将显示在应用栏的左上角。(应用栏有时称为操作栏。)向上按钮会根据屏幕之间的层次关系使用户在应用的屏幕中“向上”导航。
导航控制器的 NavigationUI
库与应用栏相集成,让用户能够通过点按应用栏中的向上按钮,从应用中的任意位置返回应用的主屏幕。
如需将导航控制器关联到应用栏,请执行以下操作:
- 在
onCreate()
中,对NavigationUI
类调用setupActionBarWithNavController()
,并传入导航控制器:
val navController = this.findNavController(R.id.myNavHostFragment)
NavigationUI.setupActionBarWithNavController(this,navController)
- 替换
onSupportNavigateUp()
方法以在导航控制器中调用navigateUp()
:
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.myNavHostFragment)
return navController.navigateUp()
}
}
选项菜单
选项菜单是指用户从应用栏中点按带有三个垂直点的图标 ...
来访问的菜单。如需创建一个选项菜单,让其包含的菜单项显示 fragment,请确保 fragment 具有 ID。然后,定义选项菜单,并为菜单项的 onOptionsItemSelected() 处理程序编码。
- 确保 fragment 具有 ID:
- 向导航图中添加目的地 fragment,并注意 fragment 的 ID。(如果愿意,您可以更改 ID。)
- 定义选项菜单:
- 创建一个类型为
Menu
的 Android 资源文件,该文件通常名为options_menu.xml
。该文件存储在Res > Menu
文件夹中。 - 在设计编辑器中打开
options_menu.xml
文件,然后将一个Menu Item
微件从Palette
窗格拖动到菜单。 - 为方便起见,请将菜单项的 ID 设为与用户点击此菜单项时要显示的 fragment 的 ID 相同。此步骤不是必需操作,但会使为菜单项的
onClick
行为编码变得更容易。
- 为菜单项的
onClick
处理程序编码:
- 在显示选项菜单的 fragment 或 activity 中,在
onCreateView()
中,调用setHasOptionsMenu(true)
以启用选项菜单。 - 实现
onCreateOptionsMenu()
以膨胀选项菜单:
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.options_menu, menu)
}
- 替换
onOptionsItemSelected()
方法以在用户点击菜单项时采取适当的操作。以下代码显示了与菜单项具有相同 ID 的 fragment。(仅当菜单项和 fragment 具有完全相同的 ID 值时,此代码才有效。)
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return NavigationUI.
onNavDestinationSelected(item,requireView().findNavController())
|| super.onOptionsItemSelected(item)
}
抽屉式导航栏
抽屉式导航栏是从屏幕边缘滑出的一个面板。用户可以通过两种方式来打开抽屉式导航栏:
- 在任意屏幕上从起始边缘(通常是左侧边缘)滑动。
- 使用应用顶部的应用栏中的抽屉式导航栏按钮(三条线)。
如需向应用中添加抽屉式导航栏,请执行以下操作:
- 将依赖项添加到
build.gradle (app)
。 - 确保每个目的地 fragment 都有一个 ID。
- 创建抽屉式导航栏的菜单。
- 将抽屉式导航栏添加到 fragment 的布局。
- 将抽屉式导航栏连接到导航控制器。
- 设置应用栏中的抽屉式导航栏按钮。
下面更为详细地介绍了这些步骤。
- 将依赖项添加到
build.gradle
:
- 抽屉式导航栏是 Material Components for Android 库的一部分。将 Material 库添加到
build.gradle (app)
文件:
dependencies {
...
implementation "com.google.android.material:material:$supportlibVersion"
...
}
- 为每个目的地 fragment 指定一个 ID:
- 如果可以从抽屉式导航栏到达某个 fragment,请在导航图中将其打开,以确保它具有一个 ID。
- 创建抽屉式导航栏的菜单:
- 为抽屉式导航栏菜单创建一个类型为
Menu
(通常名为navdrawer_menu
)的 Android 资源文件。这样会在Res > Menu
文件夹中创建一个新的navdrawer_menu.xml
文件。 - 在设计编辑器中,将
Menu Item
微件添加到Menu
。
- 将抽屉式导航栏添加到 fragment 的布局:
- 在包含导航宿主 fragment 的布局(它通常是主布局)中,使用
<androidx.drawerlayout.widget.DrawerLayout>
作为根视图。 - 将一个
<com.google.android.material.navigation.NavigationView>
视图添加到布局中。
- 将抽屉式导航栏连接到导航控制器:
- 打开创建导航控制器的 activity。(主 activity 通常是您在此处想要的 activity。)在
onCreate()
中,使用NavigationUI.setupWithNavController()
将抽屉式导航栏与导航控制器连接起来:
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(
this, R.layout.activity_main)
NavigationUI.setupWithNavController(binding.navView, navController)
- 设置应用栏中的抽屉式导航栏按钮:
- 在创建导航控制器的 activity(它通常是主 activity)的
onCreate()
中,将抽屉式导航栏布局作为第三个参数传递给NavigationUI.setupActionBarWithNavController
:
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(
this, R.layout.activity_main)
NavigationUI.setupActionBarWithNavController(
this, navController, binding.drawerLayout)
```
- 如需将向上按钮与抽屉式导航栏按钮一起使用,请修改 ```onSupportNavigateUp() ```以返回 ```NavigationUI.navigateUp() ```。将导航控制器和抽屉式导航栏布局传递给 ```navigateUp() ```。
```kotlin
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.myNavHostFragment)
return NavigationUI.navigateUp(navController, drawerLayout)
}