androidandroid-animationandroid-jetpack-compose

Jetpack compose how to wait for animation ends


I have simple animation by AnimatedVisibility (slideInVertically/SlideOut). When i press "nextScreenButton" i make new navigate by navController. The transition is done instantly, so no time for exit animation. How to make waiting until animations ends

I can enter some delay for animation time, but its not good way.

Code:

      Scaffold() {
        AnimatedVisibility(
            //Boolean State for open animation 
            OpenChooseProfilePageAnim.value,
            
            initiallyVisible= false,
            enter = slideInVertically(
                initialOffsetY = { fullHeight -> fullHeight },
                animationSpec = tween(
                    durationMillis = 3000,
                    easing = LinearOutSlowInEasing
                )
            ),
            exit = slideOutVertically(
                targetOffsetY = { fullHeight -> fullHeight },
                animationSpec = tween(
                    durationMillis = 3000,
                    easing = LinearOutSlowInEasing
                )
            )
        ) {
            ConstraintLayout() {
                Card() {
                    Column() {
                        
                        //Some other Composable items
                        
                        //Composable button
                        NextScreenButton() {
                            //calling navigation here
                        }
                    }
                }
            }
        }
    }

Ty for help.

enter image description here

NextScreenButton code:

    fun navigateToMainListPage(navController: NavController) {
        //change State of visibility for "AnimatedVisibility"
        AnimationsState.OpenChooseProfilePageAnim.value = false
        //navigate to another route in NavHost
        navController.navigate(ROUTE_MAIN_LIST)
    }

NavHost:


    @Composable
    fun LoginGroupNavigation(startDestination: String) {
        val navController = rememberNavController()
        NavHost(navController, startDestination = startDestination) {
            composable(LoginScreens.LoginScreen.route) {
                LoginMainPage(navController)
            }
            composable(LoginScreens.EnteringPhoneNumScreen.route,
                arguments = listOf(navArgument("title") { type = NavType.StringType },
            )) {
                val title =  it.arguments?.getString("title") ?: ""
                EnterPhoneNumberForSmsPage(
                    navController = navController,
                    title
                )
            }
    //more composable screens

   


Solution

  • Here is the main idea to do this:

       val animVisibleState = remember { MutableTransitionState(false) }
        .apply { targetState = true }
    
    //Note: Once the exit transition is finished,
    //the content composable will be removed from the tree, 
    //and disposed.
    //Both currentState and targetState will be false for 
    //visibleState.
    if (!animVisibleState.targetState &&
        !animVisibleState.currentState
    ) {
        //navigate to another route in NavHost
        navController.navigate(ROUTE_MAIN_LIST)
        return
    }
    
    
    AnimatedVisibility(
        visibleState = animVisibleState,
        enter = fadeIn(
            animationSpec = tween(durationMillis = 200)
        ),
        exit = fadeOut(
            animationSpec = tween(durationMillis = 200)
        )
    ) {
        NextButton() {
            //start exit animation
            animVisibleState.targetState = false
        }
    
    }