android Jetpack Navigation 组件——堆栈操作和动画效果
val navigarionResult = findNavController().navigateUp()println("是否导航出栈成功:$navigarionResult")
2、findNavController().popBackStack(R.id.AFragment,false)
这个方法用于执行返回指定页面的操作,例如本例: 进入的时候我们点击 AFragment 的按钮跳转到 BFragment,在 BFragment 中执行如下代码:
val popBackStack = findNavController().popBackStack(R.id.AFragment,false)println("是否返回:$popBackStack")
就可以指定返回 AFragment。
popBackStack 的第二个参数说明:
true:从 B 返回 A 的时候会把 A 出栈,然后重新打开 A
false:从 B 返回 A 的时候 A 不会出栈,保留跳转到 B 之前的状态
popUpTo 和 popUpToInclusive
先看一下我们的导航图代码
<?xml version="1.0" encoding="utf-8"?><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/navigation_popup"app:startDestination="@id/popUpFragment">
<fragmentandroid:id="@+id/popUpFragment"android:name="com.mage.navigationdemo.pop.PopUpFragment"android:label="fragment_pop_up"tools:layout="@layout/fragment_pop_up" ><actionandroid:id="@+id/action_popUpFragment_to_popAFragment"app:destination="@id/popAFragment" /></fragment><fragmentandroid:id="@+id/popAFragment"android:name="com.mage.navigationdemo.pop.PopAFragment"android:label="fragment_pop_a"tools:layout="@layout/fragment_pop_a" ><actionandroid:id="@+id/action_popAFragment_to_popBFragment"app:destination="@id/popBFragment" /></fragment><fragmentandroid:id="@+id/popBFragment"android:name="com.mage.navigationdemo.pop.PopBFragment"android:label="fragment_pop_b"tools:layout="@layout/fragment_pop_b" ><actionandroid:id="@+id/action_popBFragment_to_popUpFragment"app:popUpToInclusive="true"app:popUpTo="@id/popUpFragment"app:destination="@id/popUpFragment" /></fragment></navigation>
这段导航图的代码实现如下效果: 从 PopUpfragment 跳转到 PopUpAFragment 再跳转到 PopUpBFragment,正常情况下如果一直这么下去会无限跳转,产生无数个 Fragment 实例。
但是我们的代码中,在 PopBFragment 跳转 PopUpfragment 的 activion 中添加了 popUpTo 和 popUpToInclusive。
其中 popUpTo 表示从 PopBfragment 回到 PopUpfragment,过程中会把中间的 Fragment 也就是 PopAFragment 出栈,这样就不会同时存在多个 Fragment 实例了。而 popUpToInclusive 的作用就是在这个过程中将 PopUpFragment 也出栈然后重新创建。
插播一个报错
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mage.navigat
iondemo/com.mage.navigationdemo.PopUpToTestActivity}: java.lang.IllegalStateException: Activity com.mage.navigationdemo.PopUpToTestActivity@a289b29 does not have a NavController set on 2131230963
出现这个错误的场景复现:
应用首页 MainActivity 是一个导航图组件(NavHostFragment),我们再 MainActivity 的 Fragment 中使用 startActivity 方式跳转到 PopUpToTestActivity,在 PopUpToTestActivity 的 onCreate 方法中调用如下代码
findNavController(R.id.nav_popuptotest).navigate(R.id.popUpFragment)
跳到导航图 PopUpFragment,然后就报了上面的错误。
解决的方式如下面的代码:
val fragment:NavHostFragment = supportFragmentManager.findFragmentById(R.id.nav_popuptotest) as NavHostFragmentfragment.navController.navigate(R.id.popUpFragment)
即通过 supportFragmentManager 找到组件的 NavHostFragment,利用 NavHostFragment 的 NavController 进行路由跳转
!!!讲一个 findNavController().popBackStack(R.id.AFragment,true)的坑
代码如下:
从 A 跳转到 B
content.findViewById<Button>(R.id.btn_toBFragment).setOnClickListener {findNavController().navigate(R.id.action_AFragment_to_BFragment)}
从 B 使用 popBackStack(R.id.AFragment,true)返回 A
val popBackStack = findNavController().popBackStack(R.id.AFragment,true)println("是否返回:$popBackStack")
再从 A 使用导航组件跳转到 B
content.findViewById<Button>(R.id.btn_toBFragment).setOnClickListener {
评论