Closed uragiristereo closed 2 years ago
any update?
@uragiristereo Thanks for sharing. I missed this issue due to a notification issue. I'll check it out soon.
I checked this issue.
MaterialMotion
is implemented based on AnimatedContent
in Jetpack Compose Animation.
And in AnimatedContent
, I confirmed that the order of content is reversed when 'pop'.
The followings are sample codes using accompanist AnimatedNavHost
based on AnimatedContent
.
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.zIndex
import com.google.accompanist.navigation.animation.AnimatedNavHost
import com.google.accompanist.navigation.animation.composable
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
import soup.compose.material.motion.animation.materialElevationScaleIn
import soup.compose.material.motion.animation.materialElevationScaleOut
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun NestedAnimatedNavigation() {
val navHost = rememberAnimatedNavController()
CompositionLocalProvider(LocalNavigation provides navHost) {
AnimatedNavHost(
navController = navHost,
startDestination = "first",
) {
composable(
route = "first",
enterTransition = {
when (initialState.destination.route) {
"second" -> slideInHorizontally { it }
else -> null
}
},
exitTransition = {
when (initialState.destination.route) {
"second" -> materialElevationScaleOut()
else -> null
}
},
popEnterTransition = {
when (initialState.destination.route) {
"second" -> materialElevationScaleIn()
else -> null
}
},
popExitTransition = {
when (initialState.destination.route) {
"second" -> slideOutHorizontally { it }
else -> null
}
}
) {
NextScreen(
title = "First",
color = Color.Cyan,
nextRoute = "second"
)
}
composable(
route = "second",
enterTransition = {
when (initialState.destination.route) {
"first" -> slideInHorizontally { it }
"third" -> slideInHorizontally { it }
else -> null
}
},
exitTransition = {
when (targetState.destination.route) {
"first" -> materialElevationScaleOut()
"third" -> materialElevationScaleOut()
else -> null
}
},
popEnterTransition = {
when (initialState.destination.route) {
"first" -> materialElevationScaleIn()
"third" -> materialElevationScaleIn()
else -> null
}
},
popExitTransition = {
when (targetState.destination.route) {
"first" -> slideOutHorizontally { it }
"third" -> slideOutHorizontally { it }
else -> null
}
}
) {
NextScreen(
title = "Second",
color = Color.Red,
nextRoute = "third"
)
}
composable(
route = "third",
enterTransition = {
when (initialState.destination.route) {
"second" -> slideInHorizontally { it }
"fourth" -> slideInHorizontally { it }
else -> null
}
},
exitTransition = {
when (targetState.destination.route) {
"second" -> materialElevationScaleOut()
"fourth" -> materialElevationScaleOut()
else -> null
}
},
popEnterTransition = {
when (initialState.destination.route) {
"second" -> materialElevationScaleIn()
"fourth" -> materialElevationScaleIn()
else -> null
}
},
popExitTransition = {
when (targetState.destination.route) {
"second" -> slideOutHorizontally { it }
"fourth" -> slideOutHorizontally { it }
else -> null
}
}
) {
NextScreen(
title = "Third",
color = Color.Green,
nextRoute = "fourth"
)
}
composable(
route = "fourth",
enterTransition = {
when (initialState.destination.route) {
"third" -> slideInHorizontally { it }
else -> null
}
},
exitTransition = {
when (targetState.destination.route) {
"third" -> materialElevationScaleOut()
else -> null
}
},
popEnterTransition = {
when (initialState.destination.route) {
"third" -> materialElevationScaleIn()
else -> null
}
},
popExitTransition = {
when (targetState.destination.route) {
"third" -> slideOutHorizontally { it }
else -> null
}
}
) {
NextScreen(
title = "Fourth",
color = Color.Yellow
)
}
}
}
}
I found this issue before, and added the following code to fix it. https://github.com/fornewid/material-motion-compose/blob/main/core/src/main/java/soup/compose/material/motion/MaterialMotion.kt#L85
However, you have confirmed that this fix is not perfect either. So I have to think about new fixes.
val forward: Boolean = pop.not()
val density: Density = LocalDensity.current
+ val contentZIndex = remember { mutableStateOf(0f) }
AnimatedContent(
modifier = modifier,
transitionSpec = {
(motionSpec.enter.transition(forward, density) with motionSpec.exit.transition(forward, density))
.apply {
// Show forward contents over the backward contents.
- targetContentZIndex = if (forward) 0.1f else 0f
+ if (forward) {
+ contentZIndex.value += 0.0001f
+ } else {
+ contentZIndex.value -= 0.0001f
+ }
+ targetContentZIndex = contentZIndex.value
}
},
contentAlignment = contentAlignment,
) { currentState ->
content(currentState)
}
However, this is only a temporary patch.
Finally, I should request to add a feature to AnimatedContent
.
this seems to be working fine on my end, any chance to push the workaround in the jitpack repository now?
@uragiristereo Thanks for making sure it works. I'll release a new version after lunch.
working perfectly fine, thank you for the release!
I have 4 navigation routes: first, second, third, fourth.
When i try to navigate
first
->second
->third
->fourth
, the transitions behave normally as it should.However when i try to navigate back (back press)
first
<-second
<-third
<-fourth
, the only transition that behave normally is the first pop backstack (in this casethird
<-fourth
), other pop backstack just overlaps the current backstack.I'm not sure how to explain it well but i have included a sample project for testing it here and a video here