question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Animated Style pass custom variable

See original GitHub issue

Amazing work with the library, it really makes things easier!

One question, if you want animations between screen you can create custom style for each screen that overrides the default AnimatedNavHostEngine you can define for all screens in that graph. But in styles I can’t seem to find a way to pass a variable to it. For example in the documentation under ProfileTransitions.kt you have hardcoded initialOffsetX = 1000, but what if I wanted a different number (for example the exact width of the screen. I can define this for default animations, but not for each individual screen.

For example:

     ProvideWindowInsets {
        AppTheme {

            val navController = rememberAnimatedNavController()
            val viewModel: CustomViewModel = hiltViewModel()

            // We can get width of the screen this way
            BoxWithConstraints {
                val width = constraints.maxWidth
                val navHostEngine = rememberAnimatedNavHostEngine(
                    rootDefaultAnimations = RootNavGraphDefaultAnimations(
                        enterTransition = {
                            slideInHorizontally(
                                initialOffsetX = { width },
                                animationSpec = tween(
                                    durationMillis = 700,
                                    easing = FastOutSlowInEasing
                                )
                            )
                        },
                        exitTransition = {
                            slideOutHorizontally(
                                targetOffsetX = { -width },
                                animationSpec = tween(
                                    durationMillis = 700,
                                    easing = FastOutSlowInEasing
                                )
                            )
                        },
                        popEnterTransition = {
                            slideInHorizontally(
                                initialOffsetX = { -width },
                                animationSpec = tween(
                                    durationMillis = 700,
                                    easing = FastOutSlowInEasing
                                )
                            )
                        },
                        popExitTransition = {
                            slideOutHorizontally(
                                targetOffsetX = { width },
                                animationSpec = tween(
                                    durationMillis = 700,
                                    easing = FastOutSlowInEasing
                                )
                            )
                        }
                    ),
                )

                DestinationsNavHost(
                    navGraph = NavGraphs.root,
                    startRoute = NavGraphs.root.startRoute,
                    engine = navHostEngine,
                    navController = navController,
                    modifier = Modifier
                ) {

                    animatedComposable(AScreenDestination) {
                        AScreen(
                            modifier = Modifier.statusBarsPadding(),
                            viewModel = viewModel,
                          )
                    }

                    animatedComposable(BScreenDestination) {
                        BScreen(
                            modifier = Modifier.statusBarsPadding(),
                            viewModel = viewModel,
                          )
                    }
                }
            }
    }
}

In this case both will have default, then If I wanted to change the transition of BScreen, you would need to add:


object BScreenTransition: DestinationStyle.Animated {

    override fun AnimatedContentScope<NavBackStackEntry>.enterTransition(): EnterTransition? {
        return when (initialState.navDestination) {
            BScreenTransitionDestination ->
                slideInHorizontally(
                    initialOffsetX = { 1000 },
                    animationSpec = tween(2500)
                )
            else -> null
        }
    }

    override fun AnimatedContentScope<NavBackStackEntry>.exitTransition(): ExitTransition? {
        return when (targetState.navDestination) {
            BScreenTransitionDestination ->
                slideOutHorizontally(
                    targetOffsetX = { -1000 },
                    animationSpec = tween(2500)
                )
            else -> null
        }
    }

    override fun AnimatedContentScope<NavBackStackEntry>.popEnterTransition(): EnterTransition? {
        return when (initialState.navDestination) {
            BScreenTransitionDestination  ->
                slideInHorizontally(
                    initialOffsetX = { -1000 },
                    animationSpec = tween(2500)
                )
            else -> null
        }
    }

    override fun AnimatedContentScope<NavBackStackEntry>.popExitTransition(): ExitTransition? {
        return when (targetState.navDestination) {
            BScreenTransitionDestination ->
                slideOutHorizontally(
                    targetOffsetX = { 1000 },
                    animationSpec = tween(2500)
                )
            else -> null
        }
    }
}

Then in BScreen add:

@Destination(
    style = BScreenTransition::class,
)

So the animation style would be applied. This way you can’t pass the width to the BScreenTransition you can only change a fixed number inside this object. Maybe it can be done and I just don’t know how.

Thanks for the help!

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
nikolaDrljacacommented, Jul 5, 2022

First of all, amazing work and amazing library!

I’ve tinkered a bit with it for the past few days, and I’ve also encountered this issue. A quick and dirty fix might be to use the android system resources to get the screen width/height:

    val height = Resources.getSystem().displayMetrics.heightPixels
    val width = Resources.getSystem().displayMetrics.widthPixels

The only issue here is that the DisplayMetrics don’t account for the sizes of system bars, like the navigation bar and the top system bar. For horizontal transitions this is fine(I don’t think there are any system bars impacting the width of the screen), but for height based transitions this is something to be aware of.

1reaction
raamcostacommented, Jan 24, 2022

I will check a way to get screen size in all transitions then 🙂 Tbh I focused only on samples to get the current animations APIs, so I’m glad you’re trying them so I can iterate on your feedback!

I’ll leave this open until I have time to check it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Using Custom Properties to Wrangle Variations in Keyframe ...
Have you ever wondered how to customize CSS animations keyframes without using any preprocessor feature, like mixins?
Read more >
Animating with CSS Variables - Val Head
Here are 4 ways CSS Variables can be helpful for animation even if ... Quick tip: CSS Variables are also called CSS Custom...
Read more >
Using CSS custom properties (variables) - MDN Web Docs
Custom properties (sometimes referred to as CSS variables or cascading variables) are entities defined by CSS authors that contain specific ...
Read more >
How to Use CSS Variables for Animation - Web Design TutsPlus
Variable Basics. CSS variables are stored values intended for reuse throughout a stylesheet. They're accessible using the custom var() function ...
Read more >
Passing parameters to css animation - Stack Overflow
Use CSS variables and you can easily do this: document.querySelector('.p2').style.setProperty('--m','100%'); document.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found