How to achieve slide in and out animation in android compose between two Views Synchronized

Viewed 9147

I know I can use the AnimatedVisibility Composable function and achieve slide-in animation for the visibility animation, but what I want to achieve is when one layout is in entering animation the other in the exit animation, something similar to the image below.

NB : I know that I should use Navigation compose for different screens and that animation between destinations is still under development, but I want to achieve this on the content of a part of screen, similar to CrossFade Animation.

enter image description here

4 Answers

As you mentioned, this animation should be implemented by the Navigation Library and there's a ticket opened to that.

Having that in mind, I'm leaving my answer here and I hope it helps...

I'll break it in three parts:

  1. The container:
@Composable
fun SlideInAnimationScreen() {
    // I'm using the same duration for all animations. 
    val animationTime = 300 

    // This state is controlling if the second screen is being displayed or not
    var showScreen2 by remember { mutableStateOf(false) }

    // This is just to give that dark effect when the first screen is closed...
    val color = animateColorAsState(
        targetValue = if (showScreen2) Color.DarkGray else Color.Red,
        animationSpec = tween(
            durationMillis = animationTime,
            easing = LinearEasing
        )
    )
    Box(Modifier.fillMaxSize()) {
       // Both Screen1 and Screen2 are declared here...
    }
}
  1. The first screen just do a small slide to create that parallax effect. I'm also changing the background color from Red to Dark just to give this overlap/hide/dark effect.
// Screen 1
AnimatedVisibility(
    !showScreen2,
    modifier = Modifier.fillMaxSize(),
    enter = slideInHorizontally(
        initialOffsetX = { -300 }, // small slide 300px
        animationSpec = tween(
            durationMillis = animationTime, 
            easing = LinearEasing // interpolator
        )
    ),
    exit = slideOutHorizontally(
        targetOffsetX = { -300 }, =
        animationSpec = tween(
            durationMillis = animationTime, 
            easing = LinearEasing
        )
    )
) {
    Box(
        Modifier
            .fillMaxSize()
            .background(color.value) // animating the color
    ) {
        Button(modifier = Modifier.align(Alignment.Center),
            onClick = {
                showScreen2 = true
            }) {
            Text(text = "Ok")
        }
    }
}
  1. The second is really sliding from the edges.
// Screen 2
AnimatedVisibility(
    showScreen2,
    modifier = Modifier.fillMaxSize(),
    enter = slideInHorizontally(
        initialOffsetX = { it }, // it == fullWidth
        animationSpec = tween(
            durationMillis = animationTime, 
            easing = LinearEasing
        )
    ),
    exit = slideOutHorizontally(
        targetOffsetX = { it },
        animationSpec = tween(
            durationMillis = animationTime, 
            easing = LinearEasing
        )
    )
) {
    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Blue)
    ) {
        Button(modifier = Modifier.align(Alignment.Center),
            onClick = {
                showScreen2 = false
            }) {
            Text(text = "Back")
        }
    }
}

Here is the result:

enter image description here

After digging in the code of CrossFade I implemented a similar one for the cross slide and it enables reverse animation for when pressing backButton

Here it is : https://gist.github.com/DavidIbrahim/5f4c0387b571f657f4de976822c2a225

Usage Example

@Composable
fun CrossSlideExample(){
    var currentPage by remember { mutableStateOf("A") }
    CrossSlide(targetState = currentPage, reverseAnimation: Boolean = false) { screen ->
        when (screen) {
            "A" -> Text("Page A")
            "B" -> Text("Page B")
        }
    }
}

As of now, we don't have anything comparable to Activity Transitions in Compose. Jetpack should be working on them I hope. An awful lot of transition APIs are either internal or private to Compose Library so implementing a fine one is harder.

If for production, Kindly use Activity/Fragment with Navigation Host. If not use AnimatedVisibility to slide without the navigation component.

https://issuetracker.google.com/issues/172112072

Related