Android JetPack Navigation

1 篇文章 0 订阅
1 篇文章 0 订阅

Navigation:管理 Fragment 的新架构模式,如果你想,整个 App 只需要一个 Activity 即可完成;

上图中ABC三个页面是由三个 Fragment 完成,交由 Navigation 管理即可实现;

想要使用 Navigation 组件需要添加依赖,且 Android Studio 3.2 版本以上;

实现非常简单,三步完成:

① 创建 navigation 目录

② 创建 navigation.xml 文件

③ Activity 关联 navigation

最炫的是预览

第一步 :( 太简单了)

 res目录下   >>>   New   >>>   New Resource Directory 

第二步 创建 navigation.xml 文件

navigation目录下   >>>   New   >>>   Navigation Resource File 

<!-- id               ( xml 文件 navigation 的 id )
     startDestination ( 默认加载首个页面,第一个 Fragment. 注:不是 Fragment 类名,是指向下面 fragment 节点的 id )-->
<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_demo"
    app:startDestination="@+id/fragment_a">

    <!--  节点
          id     ( 节点 id,跳转指向使用 )
          name   ( Fragment 路径 )
          layout ( Fragment 布局,用于浏览 )
          label  ( 标签名称,记录这个节点的标签信息,暂时没用到 ) -->
    <fragment
        android:id="@+id/fragment_a"
        android:name="FragmentA"
        android:label="BlankFragment"
        tools:layout="@layout/fragment_a">
        <!--   负责跳转
             id          ( 跳转id,页面中执行跳转时使用 )
             destination ( 跳转的目标 fragment 的 id )
             剩下四个属性 ( 跳转动画 ) -->
        <action
            android:id="@+id/action_a_to_b"
            app:destination="@+id/fragment_b"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right" />
    </fragment>

    <fragment
        android:id="@+id/fragment_b"
        android:name="FragmentB"
        android:label="BlankFragment"
        tools:layout="@layout/fragment_b">
        <action
            android:id="@+id/action_b_to_c"
            app:destination="@+id/fragment_c"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right" />
    </fragment>

    <fragment
        android:id="@+id/fragment_c"
        android:name="FragmentC"
        android:label="BlankFragment"
        tools:layout="@layout/fragment_c"/>

</navigation>

第三步:Activity 关联 navigation

首先看下 Activity 布局文件

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".NavActivity">

    <!--  关联 navigation 和 Activity
          name           ( 告知 fragment 使用 navigation 模式关键属性,固定值,直接复制即可 )
          defaultNavHost ( true 回退操作是否进行拦截交给 Navigation 管理 )
          navGraph       ( navigation 的 xml 文件 )
    -->
    <fragment
        android:id="@+id/nav_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_demo" />

</androidx.constraintlayout.widget.ConstraintLayout>

然后看下 Activity 代码

class NavActivity : AppCompatActivity() {

    /**
     * 控制器  ( 可以在 Activity 和 Fragment 中使用 )
     * 负责操作 Navigation 框架下的 Fragment 的跳转与退出、动画、监听当前Fragment信息
     */
    lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_nav)

        // R.id.nav_fragment 是 Activity 布局里 fragment 控件的 id
        navController = Navigation.findNavController(this, R.id.nav_fragment)
    }

    override fun onSupportNavigateUp(): Boolean {
        return navController.navigateUp()
    }

    // 如果想要中间 Fragment 点击返回键关闭整个 Activity 时,重写 onBackPressed()
    override fun onBackPressed() {

        // 得到当前目的地
        val currentDes = navController.currentDestination

        if (currentDes is FragmentNavigator.Destination) {
            when (currentDes.className) {
                // 如果当前页是 FragmentB 则直接退出 Activity
                FragmentB::class.java.name -> finish()
                else -> super.onBackPressed()
            }
        } else {
            super.onBackPressed()
        }
    }

}

附: Fragment 之间跳转

      /**
       *  两种方式都可实现跳转,根据不同场景选择即可
       *  action_a_to_b ( xml 中 Action 的 id )
       */
      NavHostFragment.findNavController(this).navigate(R.id.action_a_to_b)
      Navigation.findNavController(view).navigate(R.id.action_a_to_b)

参数传递接收

        // 跳转时添加 Bundle 传递参数
        val bundle = Bundle()
        bundle.putString("nav_param_fragment_b", "fragmentB Param")
        Navigation.findNavController(view).navigate(R.id.action_b_to_c, bundle)

        // 上级 Fragment 传参
        val fragmentParam = arguments?.getString("nav_param_fragment_b")
        // Activity 传参,每个 Fragment 都可获取 ( 其他页面传递参数至 NavActivity )
        val activityParam = activity?.intent?.getStringExtra("nav_param_activity") ?: ""

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值