美文网首页
导航组件介绍

导航组件介绍

作者: ModestStorm | 来源:发表于2022-11-03 00:06 被阅读0次

Navigation 组件旨在用于具有一个主 Activity 和多个 Fragment 目的地的应用。主 Activity 与导航图相关联,且包含一个负责根据需要交换目的地的 NavHostFragment。在具有多个 Activity 目的地的应用中,每个 Activity 均拥有其自己的导航图,记录一些Navigation下的NavOptions的使用记录

    <fragment
        android:id="@+id/fragmentNavRoot"
        android:name="com.mitac.app2020.sep.nav.FragmentNavRoot"
        android:label="FragmentNavRoot"
        tools:layout="@layout/fragment_nav_root">
        <action
            android:id="@+id/action_navRoot_to_navPreference"
            app:destination="@id/fragmentNavPreference" />
        <action
            android:id="@+id/action_fragmentNavRoot_to_fragmentCategory"
            app:destination="@id/fragmentCategory" />
    </fragment>

id :就是这action的id,之后跳转用到的
destination:就是这个action要跳到的fragment的id
1.代码里如何跳转fragment?

都是通过NavController来控制的,下边是获取Controller的方法:


NavController获取方式.png
1.返回某个Fragment并且传递数据

返回到栈里的某个Fragment,会将在这需要跳转的Fragment的栈前的Fragment全部清出。

Bundle bundle = new Bundle(); bundle.putString(CommunityFragment.CITY_NAME_KEY, bean.getName());
 NavOptions navOptions = new NavOptions.Builder()
                            .setPopUpTo(R.id.communityFragment, false)
                            .build();
                    Navigation.findNavController(getView()).navigate(R.id.communityFragment, bundle, navOptions);

2.点击返回

默认后退键就返回了,activity里已经处理过了。如果我们需要点击按钮返回,那么也简单:

 findNavController().navigateUp()
3.返回到指定的Fragment

系统提供了两个api供我们调用:

findNavController().popBackStack()
findNavController().popBackStack(@IdRes int destinationId, boolean inclusive)

两个参数中,第一个@IdRes int destinationId
就是要到达的目标fragment的id,
也就是在navigation.xml文件中Fragment的id
比如:findNavController().popBackStack(R.id.homeFragment,false)

第二个参数boolean inclusive是个布尔值,是否需要目标fragment弹出栈

如果Fragment A 跳到B ,B再跳到C,然后C想直接回到A咋办?
如下,第一个参数就是A的fragment id,第二个参数是为是否A也弹出,这里肯定false了,我们要跳到A的,
如果第一个参数写B的id,那么第二个参数写成true倒是刚好.


findNavController().popBackStack(R.id.fragmentA,false)
4.跳转监听

我们导航来回跳转fragment的时候,可能用的是同一个toolbar或者bottomBar之类的,这时候切换fragment的时候我们可能需要修改标题或者borromBar,这时可以在activity里添加一个监听即可,监听里可以拿到要跳转的目的地信息以及参数.

findNavController(R.id.fragment).addOnDestinationChangedListener(this)

findNavController(R.id.fragment).removeOnDestinationChangedListener(this)

    override fun onDestinationChanged(
        controller: NavController,
        destination: NavDestination,
        arguments: Bundle?
    ) {
        println("changed=======$destination=======${arguments?.size()}")
        changeTitle(destination.label?:"...")
    }
5.跳转支持的argument传值的参数类型
argument传值参数类型.png

tips:
argType 后边是类的完整名字,带路径的
如果默认值是null的话,必须添加app:nullable="true"

        <action
            android:id="@+id/action_fragmentNavRoot_to_fragmentSearchResult"
            app:destination="@id/fragmentSearchResult"
            app:popUpToInclusive="false">
            <argument
                android:name="data1"
                android:defaultValue="@null"
                app:argType="com.xxx.app2020.sep.nav.ArgSerializableTest"
                app:nullable="true" />
            <argument
                android:name="data2"
                android:defaultValue="SUN"
                app:argType="com.xxx.app2020.sep.nav.ArgEnumTest" />
        </action>


    <fragment
        android:id="@+id/fragmentSearchResult"
        android:name="com.mitac.app2020.sep.nav.FragmentSearchResult"
        android:label="FragmentSearchResult"
        tools:layout="@layout/fragment_search_result">
        <argument
            android:name="data1"
            android:defaultValue="@null"
            app:nullable="true"
            app:argType="com.nav.ArgSerializableTest" />
        <argument
            android:name="data2"
            android:defaultValue="TODAY"
            app:argType="com.nav.ArgEnumTest" />
    </fragment>
//发送端:
val bundle = bundleOf("amount" to amount)
view.findNavController().navigate(R.id.confirmationAction, bundle)

//在接收目的地的代码中,请使用 getArguments() 方法来检索 `Bundle` 并使用其内容:
val tv = view.findViewById<TextView>(R.id.textViewAmount)
tv.text = arguments?.getString("amount")
6.混淆注意事项

您需要防止在缩减过程中混淆 ParcelableSerializableEnum 类名称。您可以通过以下两种方式来实现此目的:

使用 @Keep 注解

以下示例说明了如何在代码类定义中添加 @Keep:

@Keep class ParcelableArg : Parcelable { ... }

@Keep class SerializableArg : Serializable { ... }

@Keep enum class EnumArg { ... }
也可以在keepnames 规则中配置

您也可以将 keepnames 规则添加到您的 proguard-rules.pro 文件中,如以下示例中所示:

proguard-rules.pro

-keepnames class com.path.to.your.ParcelableArg
-keepnames class com.path.to.your.SerializableArg
-keepnames class com.path.to.your.EnumArg
7.popUpTo 和 popUpToInclusive

使用操作进行导航时,您可以选择从返回堆栈上弹出其他目的地。例如,如果您的应用具有初始登录流程,那么在用户登录后,您应将所有与登录相关的目的地从返回堆栈上弹出,这样返回按钮就不会将用户带回登录流程。

如需在从一个目的地导航到另一个目的地时弹出目的地,请在关联的 <action> 元素中添加 app:popUpTo 属性。app:popUpTo 会告知 Navigation 库在调用 navigate() 的过程中从返回堆栈上弹出一些目的地。属性值是应保留在堆栈中的最新目的地的 ID。

您还可以添加 app:popUpToInclusive="true",以表明在 app:popUpTo 中指定的目的地也应从返回堆栈中移除。
导航到目的地 | Android 开发者 | Android Developers (google.cn)

8.NavOptions配置

NavOpstions存储导航操作的特殊选项:在这里解释一下:除了目的地跳转和参数传递,其他都是特殊选项。

8.1使用位置

我们可以在两个地方设置NavOptions属性:
NavController的navigate()方法里
导航图的<action>元素里

属性作用.png
8.2使用举例

1.通过NavController的navigate()方法设置NavOptions

NavController navController = NavHostFragment.findNavController(this);
NavOptions navOptions = new NavOptions.Builder()
                .setLaunchSingleTop(true) // 设置singleTop属性
                .setPopUpTo(R.id.aFragment, true, true) // 三个参数分别为popUpToId, popUpToInclusive, popUpToSaveState
                .setRestoreState(true) // 设置restoreState属性
                .build();
navController.navigate(AFragmentDirections.actionAFragmentToBFragment(), navOptions);

2.通过<action>元素设置NavOptions

<action
    android:id="@+id/action_aFragment_to_bFragment"
    app:destination="@id/bFragment"
    app:launchSingleTop="true"
    app:popUpTo="@id/aFragment"
    app:popUpToInclusive="true"
    app:popUpToSaveState="true"
    app:restoreState="true"/>

9. 跳转Fragment带动画
NavOptions navOptions = new NavOptions.Builder()
                .setEnterAnim(R.anim.from_right) //进入动画
                .setExitAnim(R.anim.to_left)    //退出动画
                .setPopEnterAnim(R.anim.to_left)    //弹出进入动画
                .setPopExitAnim(R.anim.from_right)  //弹出退出动画
                .build();
        controller.navigate(R.id.action_oneFragment_to_twoFragment, null , navOptions);

相关文章

网友评论

      本文标题:导航组件介绍

      本文链接:https://www.haomeiwen.com/subject/rofstdtx.html