使用喷气背包导航将自定义过渡动画添加到底部导航设置

Posted

技术标签:

【中文标题】使用喷气背包导航将自定义过渡动画添加到底部导航设置【英文标题】:Adding custom transition animations to bottom navigation setup with jetpack navigation 【发布时间】:2019-06-18 01:53:42 【问题描述】:

我正在开发一个使用 jetpack 组件的应用程序。我用guide 中描述的三个片段缝合了底部导航。但是,我不知道在按下相应导航按钮时在片段之间切换时如何更改过渡动画。

据我所知,有两种创建过渡的方法:

navigate() 中将它们作为选项传递,在这种情况下没有被显式调用; 使用具有动画属性的动作,但不知道如何告诉导航使用这些动作。也许给它一个特定的ID会起作用?

那么如何设置自定义转场动画又不用放弃使用BottomNavigation.setupWithNavController(navController)

【问题讨论】:

您找到解决方案了吗? 【参考方案1】:

我认为你不能,但会对解决方案感兴趣。

如果有帮助,这里有一个解决方法:

不要将底部导航与导航控制器绑定(不要按照指南中的指示进行操作)。通过像这样设置处理程序来自己管理转换:

    bottomNav!!.setOnNavigationItemSelectedListener  item ->
        selectFragment(item)
        false
    

然后在每个片段之间创建转换并在处理程序中自己管理它们。以下是 3 的示例:

private fun selectFragment(item: MenuItem) 
    if (selectedItem == -1)
        navController.navigate(item.itemId)
    else
        navController.navigate(
                when (item.itemId) 
                    R.id.interviewsFragment ->
                        if (selectedItem == R.id.personsFragment)
                            R.id.action_personsFragment_to_interviewsFragment
                        else
                            R.id.action_questionListsFragment_to_interviewsFragment
                    R.id.personsFragment ->
                        if (selectedItem == R.id.interviewsFragment)
                            R.id.action_interviewsFragment_to_personsFragment
                        else
                            R.id.action_questionListsFragment_to_personsFragment
                    R.id.questionListsFragment ->
                        if (selectedItem == R.id.interviewsFragment)
                            R.id.action_interviewsFragment_to_questionListsFragment
                        else
                            R.id.action_personsFragment_to_questionListsFragment
                    else -> item.itemId
                )

    selectedItem = item.itemId


    // uncheck the other items.
    for (i in 0 until bottomNav!!.menu.size()) 
        val menuItem = bottomNav!!.menu.getItem(i)
        if (menuItem.itemId == item.itemId) menuItem.isChecked = true
    

在导航地图中定义动画。这是一个包含 3 个片段的示例,动画朝着被选中的项目移动,因此感觉很自然:

<fragment
    android:id="@+id/interviewsFragment"
    android:name="com.unludo.interview.interview.list.InterviewsFragment"
    android:label="InterviewsFragment" >
    <action
        android:id="@+id/action_interviewsFragment_to_personsFragment"
        app:destination="@id/personsFragment"
        app:enterAnim="@anim/enter_from_right"
        app:exitAnim="@anim/exit_to_left" />
    <action
        android:id="@+id/action_interviewsFragment_to_questionListsFragment"
        app:destination="@id/questionListsFragment"
        app:enterAnim="@anim/enter_from_right"
        app:exitAnim="@anim/exit_to_left" />
</fragment>
<fragment
    android:id="@+id/personsFragment"
    android:name="com.unludo.interview.persons.list.PersonsFragment"
    android:label="PersonsFragment" >
    <action
        android:id="@+id/action_personsFragment_to_interviewsFragment"
        app:destination="@id/interviewsFragment"
        app:enterAnim="@anim/enter_from_left"
        app:exitAnim="@anim/exit_to_right" />
    <action
        android:id="@+id/action_personsFragment_to_questionListsFragment"
        app:destination="@id/questionListsFragment"
        app:enterAnim="@anim/enter_from_right"
        app:exitAnim="@anim/exit_to_left" />
</fragment>
<fragment
    android:id="@+id/questionListsFragment"
    android:name="com.unludo.interview.questions.lists.QuestionListsFragment"
    android:label="QuestionListsFragment" >
    <action
        android:id="@+id/action_questionListsFragment_to_personsFragment"
        app:destination="@id/personsFragment"
        app:enterAnim="@anim/enter_from_left"
        app:exitAnim="@anim/exit_to_right" />
    <action
        android:id="@+id/action_questionListsFragment_to_interviewsFragment"
        app:destination="@id/interviewsFragment"
        app:enterAnim="@anim/enter_from_left"
        app:exitAnim="@anim/exit_to_right" />
</fragment>

我认为这种行为可以由组件本身管理,但现在,我认为我们必须手动管理。

干杯:)

【讨论】:

【参考方案2】:

我相信您可以通过创建 R.anim.nav_default_[Enter/Exit/PopEnter/PopExit] 动画文件的版本并将它们放在您的动画资源目录中来实现此行为。然后,组件将这些文件用于默认动画。感觉它不应该那样工作,但目前确实如此。

【讨论】:

我不知道为什么,但这对我不起作用。我创建了四个文件“R.anim.nav_default_enter”、“R.anim.nav_default_exit”、“R.anim.nav_default_pop_enter”、“R.anim.nav_default_pop_exit”,但这并没有改变什么?

以上是关于使用喷气背包导航将自定义过渡动画添加到底部导航设置的主要内容,如果未能解决你的问题,请参考以下文章

使用带有喷气背包导航组件的导航抽屉时如何更改工具栏图标(汉堡图标)

如何完成活动? (喷气背包导航)

如何将动画添加到由 AnyView 制作的自定义导航项之间的过渡?

如何在导航控制器中将过渡动画从底部更改为顶部?

在Android中使用导航组件时如何删除默认动画过渡?

防止导航到同一个片段