21

yesterday i come across with a problem that i needed to set animation from nav_graph.xml in my baseFragment and programatically get action object from current node which includes enterAnim and exitAnim resource. Could not find solution here so here we go.

First we need to feed anim folder with our animations in res folder because its hungry.

slide_in_left.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="250"
        android:fromXDelta="-100%"
        android:fromYDelta="0%"
        android:toXDelta="0%"
        android:toYDelta="0%" />
</set>

other animations you can easily found on github or stackoverflow.

Here is my nav_graph.xml fragment from which we gonna make transition

<fragment
    android:id="@+id/kebabsFragment"
    android:name="com.kebabkrabby.kebabapp.KebabFragment"
    android:label="so many kebabs"
    tools:layout="@layout/fragment_kebab">

    <action
        android:id="@+id/action_kebabs_to_kebab_detail"
        app:destination="@id/kebabDetailFragment"
        app:enterAnim="@anim/slide_in_right"
        app:exitAnim="@anim/slide_out_left" />
</fragment>

now in KebabFragment.tk u gonna call baseFragment method for transition to get into detail of our desired kebab and then popFromBackStack

//navigateAndClean(actionId, cleanFragmentId)
navigateAndClean(R.id.action_kebabs_to_kebab_detail, R.id.kebabsFragment)

in our baseFragment.kt

internal fun navigateAndClean(actionId: Int, currentFragmentIdToClear: Int) {

    val navBuilder = NavOptions.Builder()

    val navController = Navigation.findNavController(getRootView())
    val currNavigationNode = navController.graph.findNode(currentFragmentIdToClear) // NavDestination of kebabsFragment object in nav_graph.xml
    val action = currNavigationNode?.getAction(actionId) // finally we get this action_kebabs_to_kebab_detail action object

    action?.navOptions?.enterAnim?.let {  //do we have animation or not?
        navBuilder.setEnterAnim(it)
    }

    action?.navOptions?.exitAnim?.let {
        navBuilder.setExitAnim(it)
    }

    navBuilder.setPopUpTo(currentFragmentIdToClear, true)       //remove from backstack

    navController.navigate(actionId, null, navBuilder.build())
}

Some people will ask. Hey, Mr. Kebab but how do i get getRootView() and Mr. Kebab will look at u and say "buddy, look at this world, together we can achieve big things"

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    rootView = inflater.inflate(mContentLayoutResourceId, container, false)
    return rootView
}

fun getRootView(): View {
    return rootView
}

Durum kebab. Enjoy.

Kebab Krabby
  • 1,574
  • 13
  • 21
  • does `KebabFragment` extend `baseFragment`? it seems to me that the action already has the transitions embedded, why do you need to reapply them? – Stachu Oct 05 '20 at 21:43
  • Yes KebabFragment extend BaseFragment and BaseFragment holds navigateAndClean function which reads fragment settings in nav_graph.xml and apply transition if there is any. If there is any transition we put it into navBuilder. – Kebab Krabby Oct 06 '20 at 09:55
  • so you say that when action passed to `navigateAndClean` has transitions they're not applied automatically and you need to apply them manually, correct? – Stachu Oct 06 '20 at 12:05
  • navController.navigate() does not take action object but actionId thats big difference. It does not now about any transition. You have to create custom navBuilder object with animations. So you first get the action from graph with actionId then check if there is any transition if so you set it to custom navBuilder object. – Kebab Krabby Oct 06 '20 at 12:20
  • OK, clear. why not use `navController.navigate(actionId, null, action?.navOptions)`? doesn't it do the trick? – Stachu Oct 06 '20 at 12:57

1 Answers1

4

Navigation components provides built in animation options for entry and exit transitions, a sample code block is attached below for reference

Code block to add animations within java/kotlin

navigate(
navController, resId, bundle,
NavOptions.Builder()
    .setPopUpTo(R.id.splashFragment, true)
    .setEnterAnim(R.anim.fade_in)
    .setExitAnim(R.anim.fade_out)
    .setPopEnterAnim(R.anim.fade_in)
    .setPopExitAnim(R.anim.fade_out)
    .build()
)

Code block for adding animation in xml file

<fragment
android:id="@+id/kebabsFragment"
android:name="com.kebabkrabby.kebabapp.KebabFragment"
android:label="so many kebabs"
tools:layout="@layout/fragment_kebab">
<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>
Arbaz Pirwani
  • 935
  • 7
  • 22