How do I define default animations for Navigation Actions?

Smedegaard picture Smedegaard · May 23, 2018 · Viewed 12.3k times · Source

I'm using Android Studio 3.2 Canary 14 and The Navigation Architecture Component. With this you can define transition animations pretty much as you would when using Intents.

But the animations are set as properties of the actions in the navigation graph, like so:

<fragment
    android:id="@+id/startScreenFragment"
    android:name="com.example.startScreen.StartScreenFragment"
    android:label="fragment_start_screen"
    tools:layout="@layout/fragment_start_screen" >
  <action
    android:id="@+id/action_startScreenFragment_to_findAddressFragment"
    app:destination="@id/findAddressFragment"
    app:enterAnim="@animator/slide_in_right"
    app:exitAnim="@animator/slide_out_left"
    app:popEnterAnim="@animator/slide_in_left"
    app:popExitAnim="@animator/slide_out_right"/>
</fragment>

This gets tedious to define for all actions in the graph!

Is there a way to define a set of animations as default, on actions?

I've had no luck using styles for this.

Answer

Martin Zeitler picture Martin Zeitler · Sep 19, 2018

R.anim has the default animations defined (as final):

  • nav_default_enter_anim

  • nav_default_exit_anim

  • nav_default_pop_enter_anim

  • nav_default_pop_exit_anim

in order to change this behavior, you would have to use custom NavOptions,

because this is where those animation are being assigned to a NavAction.

one can assign these with the NavOptions.Builder:

protected NavOptions getNavOptions() {

    NavOptions navOptions = new NavOptions.Builder()
      .setEnterAnim(R.anim.default_enter_anim)
      .setExitAnim(R.anim.default_exit_anim)
      .setPopEnterAnim(R.anim.default_pop_enter_anim)
      .setPopExitAnim(R.anim.default_pop_exit_anim)
      .build();

    return navOptions;
}

most likely one would need to create a DefaultNavFragment, which extends class androidx.navigation.fragment (the documentation there does not seem completed yet).

So you can pass these NavOptions to the NavHostFragment like this:

NavHostFragment.findNavController(this).navigate(R.id.your_action_id, null, getNavOptions());

alternatively... when looking at the attrs.xml of that package; these animations are style-able:

<resources>
    <declare-styleable name="NavAction">
        <attr name="enterAnim" format="reference"/>
        <attr name="exitAnim" format="reference"/>
        <attr name="popEnterAnim" format="reference"/>
        <attr name="popExitAnim" format="reference"/>
        ...
    </declare-styleable>
</resources>

this means, one can define the according styles - and define these, as part of the theme...

one can define them in styles.xml:

<style name="Theme.Default" parent="Theme.AppCompat.Light.NoActionBar">

    <!-- these should be the correct ones -->
    <item name="NavAction_enterAnim">@anim/default_enter_anim</item>
    <item name="NavAction_exitAnim">@anim/default_exit_anim</item>
    <item name="NavAction_popEnterAnim">@anim/default_pop_enter_anim</item>
    <item name="NavAction_popExitAnim">@anim/default_pop_exit_anim</item>

</style>