这就是被覆盖的方法onNavigationItemSelected 的外观:
override fun onNavigationItemSelected(item: MenuItem): Boolean
{
drawerLayout.close()
// this part checks if current fragment is the same as destination
return if (findNavController(R.id.navHostFragment).currentDestination?.id != item.itemId)
{
val builder = NavOptions.Builder()
.setLaunchSingleTop(true)
.setEnterAnim(R.anim.enter_left_to_right)
.setExitAnim(R.anim.exit_right_to_left)
.setPopEnterAnim(R.anim.popenter_right_to_left)
.setPopExitAnim(R.anim.popexit_left_to_right)
// this part set proper pop up destination to prevent "looping" fragments
if (item.order and Menu.CATEGORY_SECONDARY == 0)
{
var startDestination: NavDestination? =
findNavController(R.id.navHostFragment).graph
while (startDestination is NavGraph)
{
val parent = startDestination
startDestination = parent.findNode(parent.startDestination)
}
builder.setPopUpTo(
startDestination!!.id,
false
)
}
val options = builder.build()
return try
{
findNavController(R.id.navHostFragment).navigate(item.itemId, null, options)
true
}
catch (e: IllegalArgumentException) // couldn't find destination, do nothing
{
false
}
}
else
{
false
}
}
-
此方法可防止转到当前选定的片段。因此,当用户在 Fragment A 中并在导航抽屉中再次选择 Fragment A 时,不会发生任何事情,导航抽屉将隐藏。
-
此方法还可以防止“循环”片段,堆栈上可能只有一个片段是从导航抽屉或工具栏菜单中选择的。例如。在导航抽屉中是Fragment A 和Fragment B。用户在Fragment Home,然后转到Fragment A 和Fragment B 旁边。如果用户单击返回按钮,应用程序将返回到 Fragment Home,而不是 Fragment A。此外,可以使用R.id.homeFragment,而不是在while 循环中查找startDestination。如果有人想允许“循环”片段,只需在代码中删除这部分即可。
我已经测试过这个解决方案,它似乎工作得很好,但当然也可能有些东西不能完全按照它应该的方式工作。
如果有人想要带有淡入/淡出和垂直平移的简单动画:
R.anim.enter_left_to_right
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@integer/fragment_anim_time"
android:fromXDelta="-100%"
android:fromYDelta="0%"
android:toXDelta="0%"
android:toYDelta="0%" />
<alpha
android:duration="@integer/fragment_anim_time"
android:fromAlpha="0.5"
android:toAlpha="1" />
</set>
R.anim.exit_right_to_left
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@integer/fragment_anim_time"
android:fromXDelta="0%"
android:fromYDelta="0%"
android:toXDelta="100%"
android:toYDelta="0%" />
<alpha
android:duration="@integer/fragment_anim_time"
android:fromAlpha="1"
android:toAlpha="0.5" />
</set>
R.anim.penter_right_to_left
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@integer/fragment_anim_time"
android:fromXDelta="100%"
android:fromYDelta="0%"
android:toXDelta="0%"
android:toYDelta="0%" />
<alpha
android:duration="@integer/fragment_anim_time"
android:fromAlpha="0.5"
android:toAlpha="1" />
</set>
R.anim.popexit_left_to_right
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@integer/fragment_anim_time"
android:fromXDelta="0%"
android:fromYDelta="0%"
android:toXDelta="-100%"
android:toYDelta="0%" />
<alpha
android:duration="@integer/fragment_anim_time"
android:fromAlpha="1"
android:toAlpha="0.5" />
</set>
res/values/integers.xml
<integer name="fragment_anim_time">250</integer>