FragmentContainerView和导航

FragmentContainerView和导航

1. FragmentContainerView

替代FrameLayout作为Fragment的容器。
解决了FrameLayout在Fragment过渡动画 View显示次序问题,另外支持导航功能。

使用

Android项目默认会依赖Fragment库,也可手动添加依赖:

dependencies {
    def fragment_version = "1.5.5"

    implementation "androidx.fragment:fragment:$fragment_version"
    // 支持kotlin一些拓展方法
    implementation "androidx.fragment:fragment-ktx:$fragment_version"
    // 用于Fragment的单元测试,可选
    debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
}

只需把原来FrameLayout替换成FragmentContainerView 即可:

<androidx.fragment.app.FragmentContainerView
    android:id="@+id/fragment_container_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

xml设置初始化Fragment

  • android:name 指定初始化的Fragment类
  • android:tag 初始化Fragment的tag(可选的),findFragmentByTag来获取添加的Fragment
<androidx.fragment.app.FragmentContainerView
    android:id="@+id/fragment_container_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.example.ExampleFragment"
    android:tag="my_tag" />

基本操作 添加、移除

和FrameLayout作为容器时一样,使用FragmentManager的方法:

负责添加、替换、移除事务提交和后退

  • FragmentTransaction.add/replace/remove/commit
  • FragmentManager.popBackStack
getSupportFragmentManager().beginTransaction()
    .setReorderingAllowed(true)
    .add(R.id.fragment_container_view, ExampleFragment.class, null)
    .commit();

动画过渡

和Activity类似,设置窗体动画和过渡动画:

  • FragmentTransaction.setCustomAnimations
  • FragmentTransaction.setTransition
  • Fragment.setEnterTransition/setReturnTransition
  • Fragment.setSharedElementEnterTransition

具体看官方文档:https://developer.android.com/guide/fragments/animate

2. 导航

Navigation组件允许使用导航图,来设计页面的导航跳转。

FragmentContainerView作为Fragment的容器,对于单个Activity多个Fragment来设计的APP,使用导航可以方便实现。

<androidx.fragment.app.FragmentContainerView
   android:name="androidx.navigation.fragment.NavHostFragment"
   app:navGraph="@navigation/nav_graph"
   app:defaultNavHost="true"
   android:id="@+id/main_content"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />
  • NavHostFragment 承担导航任务
  • app:navGraph 设置导航图
  • app:defaultNavHost 确保您的 NavHostFragment 会拦截系统返回按钮

在res目录创建 navigation 资源目录。然后
右键 New -> Navigation Resource File 创建 导航图文件。


<navigation 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:id="@+id/nav_graph"
    app:startDestination="@id/mainFragment">

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.example.fragmetndemo.MainFragment"
        android:label="fragment_main"
        tools:layout="@layout/fragment_main" />
navigation>

导航图

navigation标签下,可包含 activity/fragment/dialog/include 元素,它们分别对应

  • dialog 对应 DialogFragment
  • include 可包含其他导航图,可用于多模块导航

导航到目标

NavController 负责跳转页面功能。

可是使用 目标id、action、deeplink 等导航到目标。

在fragment/activity标签内,添加 action deeplink:


<action
    android:id="@+id/action_main_to_second"
    app:destination="@+id/secondFragment"
    app:enterAnim="@anim/nav_default_enter_anim"
    app:exitAnim="@anim/nav_default_exit_anim"
    app:popEnterAnim="@anim/nav_default_pop_enter_anim"
    app:popExitAnim="@anim/nav_default_pop_exit_anim" />


<deepLink app:uri="android-app://com.example.fragmentdemo/second" />

代码里使用NavControler导航:

// 使用fragment id跳转
findNavController().navigate(R.id.secondFragment)
// 使用action跳转
findNavController().navigate(R.id.action_main_to_second)
// 使用deepLink,跨模块跳转
val request = NavDeepLinkRequest.Builder
    .fromUri("android-app://com.example.fragmentdemo/second".toUri())
    .build()
findNavController().navigate(request)

详细说明:

参数

1. 在使用时,添加gradle插件:

// 在项目的顶级build.gradle 添加:

plugins {
    id 'androidx.navigation.safeargs' version '2.5.3' apply false
}

如果顶级build.gradle使用的是dependencies方式,则使用:

buildscript {
    dependencies {
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3"
    }
}

在模块build.gradle中添加:

plugins {
    id 'androidx.navigation.safeargs'
}

2. 在目标标签内,添加 argument 标签,声明参数名、类型、默认值。

<argument
    android:name="count"
    app:argType="integer"
    android:defaultValue="0" />

非基本类型,可以使用 app:nullable 声明是否可空。

3. 代码调用:

// 通过Bundle传数据
findNavController().navigate(
    R.id.action_main_to_second,
    bundleOf(
        "count" to 1
    )
)

参考文档

  • Android FragmentContainerView
  • Android Navgation组件
  • 迁移到Navigation组件

你可能感兴趣的:(Android,Android)