【问题标题】:Animate fragment transitions with using Navigation drawer or Toolbar menu使用导航抽屉或工具栏菜单动画片段过渡
【发布时间】:2020-08-07 00:42:46
【问题描述】:

我有一个导航抽屉和工具栏菜单,我可以在其中转到另一个片段。我用它来导航:

override fun onNavigationItemSelected(item: MenuItem): Boolean
{
    drawerLayout.close()
    return NavigationUI.onNavDestinationSelected(
        item,
        findNavController(R.id.navHostFragment)
    )
}

如何在切换片段时添加自定义动画?


Answer your own question。我遇到了这个问题,但找不到任何在我的情况下可以 100% 有效的答案,所以也许这会对某人有所帮助。

【问题讨论】:

    标签: android kotlin navigation-drawer android-toolbar android-navigation


    【解决方案1】:

    这就是被覆盖的方法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
        }
    }
    
    1. 此方法可防止转到当前选定的片段。因此,当用户在 Fragment A 中并在导航抽屉中再次选择 Fragment A 时,不会发生任何事情,导航抽屉将隐藏。

    2. 此方法还可以防止“循环”片段,堆栈上可能只有一个片段是从导航抽屉或工具栏菜单中选择的。例如。在导航抽屉中是Fragment AFragment B。用户在Fragment Home,然后转到Fragment AFragment 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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-23
      • 1970-01-01
      • 2023-03-13
      相关资源
      最近更新 更多