使用Architecture Navigation Components为BottomNavigation Fragments添加动画效果

14

我已经成功地将底部导航与最新的Android架构导航组件集成。以下是我的完整代码。

  1. 导航
<?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/mobile_navigation"
    app:startDestination="@+id/navigation_home">

    <fragment
        android:id="@+id/navigation_home"
        android:name="in.zedone.bottomsample.ui.home.HomeFragment"
        android:label="@string/title_home"
        tools:layout="@layout/fragment_home" />

    <fragment
        android:id="@+id/navigation_saloons"
        android:name="in.zedone.bottomsample.ui.saloons.SaloonsFragment"
        android:label="@string/title_saloon"
        tools:layout="@layout/fragment_saloons" />

    <fragment
        android:id="@+id/navigation_offers"
        android:name="in.zedone.bottomsample.ui.offers.OffersFragment"
        android:label="@string/title_offer"
        tools:layout="@layout/fragment_offers" />

    <fragment
        android:id="@+id/navigation_account"
        android:name="in.zedone.bottomsample.ui.account.AccountFragment"
        android:label="@string/title_account"
        tools:layout="@layout/fragment_account" />

</navigation>
底部导航视图
<com.google.android.material.bottomnavigation.BottomNavigationView
     android:id="@+id/nav_view"
     android:layout_width="0dp"
     android:layout_height="wrap_content"
     android:layout_marginStart="0dp"
     android:layout_marginEnd="0dp"
     android:background="?android:attr/windowBackground"
     app:labelVisibilityMode="labeled"
     app:itemTextAppearanceActive="@style/BottomNavigationView.Active"
     app:itemTextAppearanceInactive="@style/BottomNavigationView"
     app:layout_constraintBottom_toBottomOf="parent"
     app:layout_constraintLeft_toLeftOf="parent"
     app:layout_constraintRight_toRightOf="parent"
     app:menu="@menu/bottom_nav_menu" />
  1. MainActivity
这是一个Android应用程序中的主要活动,它充当了用户界面和其他组件之间的桥梁。它是应用程序启动时第一个加载的组件,并且通常包括应用程序的主要交互逻辑和功能。
BottomNavigationView navView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_home, R.id.navigation_saloons, R.id.navigation_offers,R.id.navigation_account)
                .build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);

现在我该如何在底部导航中选择每个选项卡/片段时添加过渡/动画效果呢?


3
你找到方法做那件事了吗?根据你的问题,答案不正确,因为你没有行动。 - Francesco Bonizzi
4个回答

17

不使用setupWithNavController函数,按照以下方式进行操作。

首先,创建包含下面显示的动画的NavOptions。

val options = NavOptions.Builder()
            .setLaunchSingleTop(true)
            .setEnterAnim(R.anim.enter_from_bottom)
            .setExitAnim(R.anim.exit_to_top)
            .setPopEnterAnim(R.anim.enter_from_top)
            .setPopExitAnim(R.anim.exit_to_bottom)
            .setPopUpTo(navController.graph.startDestination, false)
            .build()
然后使用setOnNavigationItemSelectedListener来实现带有动画的导航,就像这样。
bottomNavigationView.setOnNavigationItemSelectedListener { item ->
        when(item.itemId) {
            R.id.fragmentFirst -> {
                navController.navigate(R.id.fragmentFirst,null,options)
            }
            R.id.fragmentSecond -> {
                navController.navigate(R.id.fragmentSecond,null,options)
            }
            R.id.fragmentThird -> {
                navController.navigate(R.id.fragmentThird,null,options)
            }
        }
         true
    }

最后,您应该防止选择相同的物品,以便可以添加以下代码。

bottomNavigationView.setOnNavigationItemReselectedListener { item ->
        return@setOnNavigationItemReselectedListener

我在我的项目中使用了bottomNavigation来添加页面转换的动画。希望对你有所帮助。


2
这是我能找到的唯一简单且无错误的解决方案,完美地运行并应该被接受为答案。只需记得删除“setupwithnavcontroller”。谢谢! - m.i.n.a.r.
我从哪里获取动画?“R.anim.enter_from”等都是红色的。 - Andrew
1
嗨@Andrew,你可以将anim文件夹添加到res目录中,并通过Google搜索添加你的动画,然后将名称更改为你自己的。例如:enter_from_bottom.xml应该是<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> <translate android:fromXDelta="0%" android:toXDelta="0%" android:fromYDelta="100%" android:toYDelta="0%" android:duration="@integer/anim_duration"/> </set> - thegirlincode
@thegirlincode 对于上述代码,如果我现在选择一个 Fragment,然后过一段时间再次选择相同的 Fragment,新的 Fragment 对象会被创建而不是显示旧的 Fragment 对象,请问如何解决这个问题? - Prateek Gupta

4

它可以与BottomNavigationView的兄弟片段一起使用(JetPack导航组件)。

// FragmentA.kt
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)

  exitTransition = MaterialFadeThrough()
}


// FragmentB.kt
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)

  enterTransition = MaterialFadeThrough()
}

1
您好,欢迎来到StackOverflow。请提供更多有关问题的细节以及您期望的解决方案。 - Dhanuka Perera
这个方法很容易实现。然而,在片段转换中存在明显的延迟。 - Victor Loveday

1

您还可以通过在每个Fragment中覆盖onCreateAnimation()并检查您是否使用enter参数进入或退出Fragment以及创建适当的Animation,同时保持使用setupWithNavController

override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
    return if (enter) {
        AnimationUtils.loadAnimation(context, R.anim.fade_in)
    } else {
        AnimationUtils.loadAnimation(context, R.anim.fade_out)
    }
}

针对 iloo 的回复进行编辑:

根据 Material Design(https://material.io/components/bottom-navigation#behavior)的规定,你首先不应该这样做,但我想这仍然是可以实现的。

由于使用 setupWithNavController 时所有目标都是顶级目标,因此只会有一个 previousBackStackEntry,其目标指向主目标,因此 previousBackStackEntry 对于确定你从哪个 Fragment 跳转而来并没有太大帮助。

另一种方法可能是在 Activity 中设置一个公共变量,在每个 Fragment 恢复时将最后一个目标存储在该变量中。你可以在 onAnimationCreate 中检查该变量以了解你正在从哪个 Fragment 跳转,并应用适当的动画。


对我来说,当动画不依赖于底部导航菜单中项目的位置相对于其他项目时,这种方法效果很好。淡入淡出可以工作,因为它没有方向。但是,如果您希望视图从左侧或右侧滑入,并根据其“视图行上的位置”向左或向右滑出,则传入的参数不足够。这种方法能否详细说明,以便用于这种情况? - iloo

-3

我对Android Navigation有点新,但我认为如果您想更改默认动画,可以尝试以下方法

将这些文件放入您的anim目录中

nav_default_enter_anim.xml
nav_default_exit_anim.xml
nav_default_pop_enter_anim.xml
nav_default_pop_exit_anim.xml

默认的交易动画将会改为您在上述文件中设置的动画。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接