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

Base z-order on visibleEntries #1384

Merged
merged 2 commits into from Nov 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -19,6 +19,7 @@ package com.google.accompanist.navigation.animation
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedContentScope
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.ExperimentalAnimationApi
Expand Down Expand Up @@ -195,11 +196,16 @@ public fun AnimatedNavHost(
transition.AnimatedContent(
modifier,
transitionSpec = {
val zIndex = if (composeNavigator.isPop.value) {
visibleEntries.indexOf(initialState).toFloat()
} else {
visibleEntries.indexOf(targetState).toFloat()
}
// If the initialState of the AnimatedContent is not in visibleEntries, we are in
// a case where visible has cleared the old state for some reason, so instead of
// attempting to animate away from the initialState, we skip the animation.
if (initialState in visibleEntries) {
finalEnter(this) with finalExit(this)
ContentTransform(finalEnter(this), finalExit(this), zIndex)
} else {
EnterTransition.None with ExitTransition.None
}
Expand Down
Expand Up @@ -23,10 +23,14 @@ import androidx.compose.animation.AnimatedContentScope
import androidx.compose.animation.AnimatedVisibilityScope
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.core.FiniteAnimationSpec
import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandIn
import androidx.compose.animation.fadeIn
import androidx.compose.animation.shrinkOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
Expand All @@ -44,7 +48,9 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import androidx.navigation.NavController
import androidx.navigation.NavHostController
import com.google.accompanist.navigation.animation.AnimatedNavHost
Expand All @@ -60,7 +66,25 @@ class AnimatedNavHostSample : ComponentActivity() {

setContent {
AccompanistSampleTheme {
ExperimentalAnimationNav()
val navController = rememberAnimatedNavController()
AnimatedNavHost(navController, "select") {
composable("select") {
Column {
Button(onClick = { navController.navigate("sample") }) {
Text("AnimationNav")
}
Button(onClick = { navController.navigate("zOrder") }) {
Text("Z-ordered Animations")
}
}
}
composable("sample") {
ExperimentalAnimationNav()
}
composable("zOrder") {
NavTestScreen()
}
}
}
}
}
Expand Down Expand Up @@ -316,3 +340,73 @@ fun NavigateBackButton(navController: NavController) {
}
}
}

object Destinations {
const val Login = "login"
const val Home = "home"
}

@ExperimentalAnimationApi
@Composable
fun NavTestScreen() {
val navController = rememberAnimatedNavController()
AnimatedNavHost(
navController = navController,
startDestination = Destinations.Login,
modifier = Modifier.fillMaxSize()
) {
composable(
Destinations.Login,
enterTransition = { NavigationTransition.IdentityEnter },
exitTransition = { NavigationTransition.IdentityExit },
) {
Button(onClick = {
navController.navigate(Destinations.Home)
}) {
Text(text = "Next")
}
}
composable(
route = Destinations.Home,
enterTransition = { NavigationTransition.slideInBottomAnimation },
exitTransition = { NavigationTransition.slideOutBottomAnimation },
) {
Button(
onClick = {
navController.popBackStack()
},
colors = ButtonDefaults.buttonColors(backgroundColor = Color.Yellow),
modifier = Modifier.zIndex(100f)
) {
Text(text = "label")
}
}
}
}

object NavigationTransition {
private val animation: FiniteAnimationSpec<IntOffset> = tween(
easing = LinearOutSlowInEasing,
durationMillis = 2000,
)

val IdentityEnter = slideInVertically(
initialOffsetY = {
-1 // fix for https://github.com/google/accompanist/issues/1159
},
animationSpec = animation
)

val IdentityExit = slideOutVertically(
targetOffsetY = {
-1 // fix for https://github.com/google/accompanist/issues/1159
},
animationSpec = animation
)

var slideInBottomAnimation =
slideInVertically(initialOffsetY = { fullHeight -> fullHeight }, animationSpec = animation)

var slideOutBottomAnimation =
slideOutVertically(targetOffsetY = { fullHeight -> fullHeight }, animationSpec = animation)
}