Reputation: 405
I have successfully integrated the bottom navigation with the latest android architecture navigation components. The following is my complete code.
<?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" />
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);
Now how can I add transition/animation on select each tab/fragment in bottom navigation?
Upvotes: 14
Views: 12557
Reputation: 475
You can also do it with keeping setupWithNavController
by overriding onCreateAnimation()
in each Fragment
and checking whether or not you're entering or exiting the Fragment
with the enter
parameter and then creating the appropriate Animation
with AnimationUtils.loadAnimation(context, animationId)
.
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)
}
}
EDIT as a response to iloo:
According to Material Design (https://material.io/components/bottom-navigation#behavior) you shouldn't be doing that in the first place, but I guess it's still achievable.
Since when using setupWithNavController
all destinations are top level there will
ever be only one previousBackStackEntry
whose destination points to the home
destination, therefore previousBackStackEntry
is not much of a help in figuring out which Fragment
are you coming from.
Other approach could be to have a public variable in the Activity
, where you will store the
last destination you were in and set that variable in each Fragment
upon resuming.
And you can check that variable in onAnimationCreate
to know which Fragment
you're coming from
and apply an appropriate animation.
Upvotes: 1
Reputation: 404
Instead of using setupWithNavController function, follow this way.
First, create your NavOptions which include animation shown below.
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()
Then use setOnNavigationItemSelectedListener to navigate with animation like that.
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
}
Finally, you should prevent same item selection case so you can add below code.
bottomNavigationView.setOnNavigationItemReselectedListener { item ->
return@setOnNavigationItemReselectedListener
I used bottomNavigation like that in my project to add animation for page transitions. I hope it helped.
Upvotes: 17
Reputation: 41
its work with BottomNavigationView's siblings fragment also(JetPack Navigation Components)
// FragmentA.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
exitTransition = MaterialFadeThrough()
}
// FragmentB.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialFadeThrough()
}
Upvotes: 4