Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Screen based animation overrides #1901

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open

Conversation

stagg
Copy link
Collaborator

@stagg stagg commented Jan 21, 2025

About

Building out a surface where navigation transitions can be overridden at navigation time based on the type of navigation event and the source/target screens.

Due to how shared element transitions work with AnimatedContent, we need some ability to completely replace the the transition spec before the target shared elements are loaded into the composition. Can look at PetDetailAnimatedNavigationOverride for an example of this.

AnimatedNavigationTransform usage

Transition Spec

  • This method receives a AnimatedNavigationTransform.NavigationEvent indicating the type of
    navigation event that is occurring (GoTo, Pop, RootReset).
  • It also has access to the current AnimatedContentTransitionScope, from which you can get the
    initialState and targetState of the transition, as well as use the helper functions.
  • Return a ContentTransform if you want to override the default transition for the given
    NavigationEvent and state, return null otherwise.

Transition Selection

  • When a transition is happening, the AnimatedNavDecoration will compare each of the available
    AnimatedNavigationTransforms and select the first one that is able to handle the current
    transition. If no AnimatedNavigationTransform is able to handle the transition, then the
    default transition provided by the AnimatedNavDecorator.defaultTransform will be used.

Example

object PetDetailAnimatedNavigationOverride : AnimatedNavigationTransform {

  override fun AnimatedContentTransitionScope<AnimatedNavState>.transitionSpec(
    navigationEvent: NavigationEvent
  ): ContentTransform? {
    return when {
      navigationEvent == NavigationEvent.GoTo &&
        initialState.screen is HomeScreen &&
        targetState.screen.isSharedElementDetailScreen() -> {
        // We're expecting shared elements to exist between the source and target so remove the
        // default animations.
        EnterTransition.None togetherWith ExitTransition.None
      }
      else -> null
    }
  }
}

The example checks if the user is navigating to the PetDetailScreen from the HomeScreen, with the information needed to tie together a shared element transition. If that is the case no transitions are used, otherwise it returns null to continue checking other AnimatedNavigationTransforms or fallback to the AnimatedNavDecorator.defaultTransform.

Demo

Notice how on the forward navigation the grid view is sliding out, on the pop AndroidPredictiveBackNavDecorator already removes the animation.

Before After
before.mp4
after.mp4

Questions

  • Does AnimatedNavigationTransform make sense as a general interceptor?
    • I'm a bit split on iterating over all of them at the moment in the animatedNavigationOverride method
  • Should the override be directly tied to a particular Screen?
    • Like how Ui and Presenters are via CircuitInject, or other navigation setups.
  • Should a user be able to provide an override at navigation time?
    • Think this is some extra property or context on the Navigator methods
  • If the above all makes sense what should the DI story for this look like?
    • Thinking it'd be nice to also "CircuitInject" the AnimatedNavigationTransform implementations into the Circuit instance

@stagg stagg marked this pull request as ready for review February 11, 2025 19:14
@stagg stagg requested a review from ZacSweers February 11, 2025 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant