How to add animation to changing fragments using Navigation Component? - android

How to add animation to changing fragments using Navigation Architecture Component?

In the Navigation Component documentation(https://developer.android.com/topic/libraries/architecture/navigation/navigation-implementing) in the section: Create a transition between destinations (it's near the end of the document) you have it explained in detail.
You can either add them using the editor by selecting the arrow of the desired transition and then selecting the animations in the Animations section of the Attributes tab.
Or by referencing the animations in the xml file like in the example:
<fragment
android:id="#+id/specifyAmountFragment"
android:name="com.example.buybuddy.buybuddy.SpecifyAmountFragment"
android:label="fragment_specify_amount"
tools:layout="#layout/fragment_specify_amount">
<action
android:id="#+id/confirmationAction"
app:destination="#id/confirmationFragment"
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>
You can use regular anim resources for this animations

If you want to add animation through programmatically, use NavOptions (here).
NavOptions.Builder navBuilder = new NavOptions.Builder();
navBuilder.setEnterAnim(R.anim.slide_left).setExitAnim(R.anim.slide_right).setPopEnterAnim(R.anim.slide_left).setPopExitAnim(R.anim.slide_right);
//Inside Activity
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
navController.navigate(R.id.destinationFragmentId,null,navBuilder.build());
//Inside Fragment
NavHostFragment.findNavController(YoutFragment.this)
.navigate(R.id.destinationFragmentId, null, navBuilder.build());

Related

NavigationController does not open new fragment if it is already associated with bottom navigation

I have a fragment in bottom navigation when try to launch new fragment with same id using navigation controller instead of launching new fragment it redirects me to bottom navigation tab.
here is my code
<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/home_navigation"
app:startDestination="#id/splashFragment">
<fragment
android:id="#+id/baseTabsFragment"
android:name="com.abc.abc.fragment.BaseTabsFragment"
android:label="BaseTabsFragment"
tools:layout="#layout/fragment_common_tabs">
<action
android:id="#+id/action_to_baseFragment"
app:destination="#id/baseTabsFragment"
app:launchSingleTop="false" />
</fragment>
</navigation>
And code to navigate.
findNavController().navigate(R.id.action_to_baseFragment)
Here is a link for more details on this
https://issuetracker.google.com/issues/262076827
Update: I want to avoid the code duplication. I will have same fragments with same actions but different id's looking for a better way to do it.
If i understand correctly, you want to navigate to the same fragment and fragment does not refresh.
If you use navigation component in visual interface you need to pull an arrow from your baseFragment onto baseFragment again, with this you will see an arrow like self pointed. If you don't use visual just paste below code and it will be created.
<action
android:id="#+id/action_to_BaseFragment"
app:destination="#id/baseTabsFragment"
app:popUpTo="#id/baseTabsFragment"
app:popUpToInclusive="true" />
We are using this way because if we want system to navigate, it needs different location then previous, as long as we using same fragment we need to pop the old one.
It happened due to bottom menu. In this case you need to call programmatically to click on that bottom button.
Replace
findNavController().navigate(R.id.action_to_baseFragment)
to
navController.navigate(
R.id.base_graph, null,
NavOptions.Builder().setPopUpTo(navController.graph.startDestinationId, true).build()
)

Bottom navigation bar malfunctions when navigating from a fragment

I'm using the bottom navigation bar with the navigation component
To make the two components work together I called:
bottomNavigationView.setupWithNavController(navController)
Everything works as expected except when I navigate from inside a fragment instead of the bottom navigation bar
"View all" opens the same fragment as "Reports" from the bottom navigation bar
binding.viewAllScansTv.setOnClickListener {
val action = MainFragmentDirections.actionMainFragmentToReportsFragment()
navController.navigate(action)
}
After clicking on "View all", the fragment is opened, the "Reports" button gets selected, however, navigating back "Home" does not work anymore
How can I fix this weird behavior?
The nav graph:
<navigation app:startDestination="#id/mainFragment">
<fragment
android:id="#+id/mainFragment"
android:name="com.package.name.ui.main.MainFragment"
android:label="MainFragment">
<action android:id="#+id/action_mainFragment_to_reportsFragment"
app:destination="#id/reportsFragment" />
</fragment>
</navigation>
The bottom navigation menu:
<menu>
<item
android:id="#+id/mainFragment"
android:title="Home"/>
<item
android:id="#+id/reportsFragment"
android:title="Reports"/>
<item
android:id="#+id/settingsFragment"
android:title="My account"/>
</menu>
As #ianhanniballake mentioned in a comment, a similar question was posted here
What I ended up doing was replacing
val action = MainFragmentDirections.actionMainFragmentToReportsFragment()
navController.navigate(action)
with
val item = mainBottomNavigationView.menu.findItem(R.id.reportsFragment)
NavigationUI.onNavDestinationSelected(item, navController)
So basically I used the NavigationUI API to navigate so that it correctly tracks the back stack. The same NavigationUI API is being used by the BottomNavigationView internally
Setting a click listener on any view should have the same effect as if the user taps the corresponding item in the bottom navigation. So you need to call setSelectedItemId() on the BottomNavigationView.
val mainBottomNav =
activity?.findViewById(R.id.homeBottomNavigation)
mainBottomNav?.selectedItemId = R.id.baseHomeFragment
Your current answer is fine but if you need to pass arguments it wont work, So use this
In the Navigation XML add these lines to the action
app:launchSingleTop="true"
app:popUpTo="#+id/main_navigation"
app:popUpToInclusive="true"
And make sure app:popUpTo="#+id/main_navigation" has the same id as your navigation xml
So the final action should look like:
<action
android:id="#+id/action_cameraFragment_to_searchFragment"
app:destination="#id/searchFragment"
app:launchSingleTop="true"
app:popUpTo="#+id/main_navigation"
app:popUpToInclusive="true"/>
And Navigate normally using the action
val action = CameraFragmentDirections.actionCameraFragmentToSearchFragment()
findNavController().navigate(action)

BottomNavigationView icons not highlighted with Navigation 2.4

I updated to Navigation 2.4 (def nav_version = "2.4") and now when tapping on a BottomNavigationView item it does not always highlight the icon or show the fragment the BottomNavigationView item id points to.
There are 3 bottom navigation tabs called Home, Actions, My Progress. From the Home fragment, you can navigate to SubFragment.
So the flow might be to start at Home --> go to SubFragment --> go to Actions with the BottomNavigationView --> and then tap on Home to go back. What this did before the update was open the Home fragment (desired behavior). Now when tapping on the Home icon it shows SubFragment and does not highlight the icon.
More details
This is the navController setup:
bottomNavigationView = findViewById(R.id.bottom_navigation_view)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
bottomNavigationView.setupWithNavController(navController)
The nav_graph structure is like this:
<fragment
android:id="#+id/home"
android:name="com.example.app.home"
android:label="Home"
tools:layout="#layout/home"
<action
android:id="#+id/action_home_fragment_to_sub_fragment"
app:destination="#id/sub_fragment"/>
</fragment>
<fragment
android:id="#+id/subfragment"
android:name="com.example.app.subfragment"
android:label="Sub Fragment"
tools:layout="#layout/subfragment" />
<fragment
android:id="#+id/actions"
android:name="com.example.app.actions"
android:label="Actions"
tools:layout="#layout/actions" />
<fragment
android:id="#+id/myprogress"
android:name="com.example.app.myprogress"
android:label="My Progress"
tools:layout="#layout/myprogress" />
The menu items id's for the BottomNavigationView are identical to nav_graph.
I thought the issue might be with the nav_graph structure not playing well with the new SDK, so I tried adjusting the structure of the nav_graph so that each navigation tab was within its own like this question answer has setup. It highlights the tab with this approach but still does not navigate to Home like the example above. Only to SubFragment.
Ideas on what I might be missing are appreciated!
Haven't figured out a fix for the issue yet, so downgraded to def nav_version = "2.3.5" and navigation works properly again.
This is the version before Navigation 2.4 as mentioned by # ianhanniballake above in comments.
I also came across with this issue. It is not a bug in the library.
Actually, when you link menu.xml with nav_graph.xml
You only specified only one fragmentId for each destination. Therefore, it is natural for icon not to change its current state when subfragment is selected.
Instead, you should use nested navigation graphs and use the id of that graph for menu.xml.
<navigation
android:id="#+id/home_destination"
app:startDestination="#id/home" >
<fragment
android:id="#+id/home"
android:name="com.example.app.home"
android:label="Home"
tools:layout="#layout/home"
<action
android:id="#+id/action_home_fragment_to_sub_fragment"
app:destination="#id/sub_fragment"/>
</fragment>
<fragment
android:id="#+id/subfragment"
android:name="com.example.app.subfragment"
android:label="Sub Fragment"
tools:layout="#layout/subfragment" />
</navigation>
<fragment
android:id="#+id/actions"
android:name="com.example.app.actions"
android:label="Actions"
tools:layout="#layout/actions" />
<fragment
android:id="#+id/myprogress"
android:name="com.example.app.myprogress"
android:label="My Progress"
tools:layout="#layout/myprogress" />
And when you are specifying the navigation_menu you will do like this:
<item
android:id="#+id/home_destination"
android:icon="#drawable/ic_read_quran"
android:title="#string/read_quran"
app:showAsAction="always" />

How to add transition animation to all actions in Jetpack Navigation?

To add transition animation in Jetpack navigation, we can add animation attributes to action like below in xml
<action
android:id="#+id/action_fragment1_to_fragment2"
app:destination="#id/fragment2"
app:enterAnim="#anim/slide_in_right"
app:exitAnim="#anim/slide_out_left"
app:popEnterAnim="#anim/slide_in_left"
app:popExitAnim="#anim/slide_out_right"/>
To make it pragmatically
NavOptions navOptions = new NavOptions.Builder()
.setEnterAnim(R.anim.slide_in_right)
.setExitAnim(R.anim.slide_out_left)
.setPopEnterAnim(R.anim.slide_in_left)
.setPopExitAnim(R.anim.slide_out_right)
.build();
But in my case I have so many fragments in the project and it would be a tedious task to define animation over every single actions,
Is there anyway we can define animation for every action at once and it will apply transition animation to every actions?
Thanks in advance!

Add Transition File in Navigation Graph of Android Application

I want to add an explode transition in my next fragment using the latest Navigation pattern "Navigation Graph".How to add a transition XML file(#transition/fade or #transition/slide or #transiton/explode) into Navigation Graph of android app.
You will probably want to define the desired transition in your navigation graph like this:
<fragment
// here your fragment is defined
<action
android:id="#+id/your_action_id"
app:destination="#id/yourDestinationFragment"
app:enterAnim="#anim/fade_in"
app:exitAnim="#anim/fade_out"
app:popEnterAnim="#anim/fade_in"
app:popExitAnim="#anim/fade_out" />
</fragment>
Note that you can define different animations for entering and leaving a fragment.
The animations you define will go into the /res/anim folder. You might have to create it if you don't find it.

Categories

Resources