Navigation Component set transition animation prog

2020-02-25 23:08发布

问题:

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.