如何使用底部导航视图更改选项卡切换之间的动画?

Rub*_*zen 5 android-architecture-navigation

我刚刚更新了我的代码,以使用最新的 2.4.0-alpha05 作为导航组件,并且我在多个堆栈之间进行了自定义导航,我的主导航图就像我找到的文档一样。

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:startDestination="@+id/accounts"
    android:id="@+id/bottom_nav">
    <inclue app:graph="@navigation/accounts_tab_nav"/>
    <include app:graph="@navigation/contact_tab_nav" />
    <include app:graph="@navigation/profile_tab_nav" />
</navigation>
Run Code Online (Sandbox Code Playgroud)

我的大多数堆栈都通过从右到左的幻灯片进行动画处理。看起来,当我在第二个屏幕上时,比如说配置文件屏幕,然后切换到第一个选项卡,它会触发在配置文件选项卡中通向第二个屏幕的操作中定义的popEnteren 。popExitAnim就像这样:

<fragment
    android:id="@+id/profileMain"
    android:name="com.app.ProfileFragment"
    tools:layout="@layout/fragment_profile">
    <action
        android:id="@+id/action_profileMain_to_secondFragment"
        app:destination="@id/secondFragment"
        app:enterAnim="@anim/slide_in_right"
        app:exitAnim="@anim/slide_out_left"
        app:popEnterAnim="@anim/slide_in_left"
        app:popExitAnim="@anim/slide_out_right" />
</fragment>
Run Code Online (Sandbox Code Playgroud)

但显然我希望在切换选项卡时使用(默认)淡入淡出动画。那么我应该怎么做呢?

我想在重新选择选项卡时弹出到堆栈的根目录。但我可能必须自己做?

hdo*_*ort 1

我想出了一个似乎对我有用的解决方案,但我不得不承认它感觉有点老套。

我的 MainActivity 中有一个公共标志:

var tabWasSelected = false
Run Code Online (Sandbox Code Playgroud)

然后我记得是否在 setOnItemSelectedListener 中选择了选项卡项

// always show selected Bottom Navigation item as selected (return true)
bottomNavigationView.setOnItemSelectedListener { item ->      
  // In order to get the expected behavior, you have to call default Navigation method manually
  NavigationUI.onNavDestinationSelected(item, navController)

  // set flag so that the fragment can call the correct animation on tab change in onCreateAnimation
  tabWasSelected = true

  return@setOnItemSelectedListener true
}
Run Code Online (Sandbox Code Playgroud)

这将始终选择该项目并导航到关联的目的地,同时维护多个返回堆栈。

然后我创建了一个 Fragment 类,所有其他片段都继承自该类。它只是重写 onCreateAnimation 来设置正确的动画。它看起来是这样的:

open class MyFragment: Fragment() {
    
    override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
        val activity = requireActivity()
        if (activity is MainActivity) {
            if (activity.tabWasSelected) {
                if (enter) {
                    //flow is exit first, then enter, so we have to reset the flag on enter               
                    //in order that following animations will run as defined in the nav graph
                    activity.tabWasSelected = false
                    return AnimationUtils.loadAnimation(requireContext(), R.anim.nav_default_pop_enter_anim)
                } else {
                    return AnimationUtils.loadAnimation(requireContext(), R.anim.nav_default_pop_exit_anim)
                }
            }
        }
        //no tab was selected, so run the defined animation
        return super.onCreateAnimation(transit, enter, nextAnim)
    }
}
Run Code Online (Sandbox Code Playgroud)