Skip to content

Commit

Permalink
Support zIndex Config for Transition (#446)
Browse files Browse the repository at this point in the history
* support zIndex config for transition

* update samples

* update api

* fix lint

* fix lint

* pass contentAlignment & contentKey params

* revert ScreenTransition

* update AnimatedContent

* set zIndex default as null

* update api
  • Loading branch information
qdsfdhvh authored Jun 28, 2024
1 parent 1fe759e commit e14783e
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,46 @@ abstract class BaseSampleScreen(
val color = remember {
colors.getOrNull(index % colors.size) ?: colors.random()
}
val contentColor = remember {
color.average()
}

Column(
modifier = Modifier
.fillMaxSize()
.background(color.copy(alpha = 0.3f))
.background(color)
.padding(40.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Screen $index",
fontSize = 24.sp,
fontWeight = FontWeight.Bold
fontWeight = FontWeight.Bold,
color = contentColor
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = transitionType,
fontSize = 18.sp
fontSize = 18.sp,
color = contentColor
)
}
}
}

private fun Color.average(): Color {
return Color((255 - red * 255) / 255, (255 - green * 255) / 255, (255 - blue * 255) / 255, alpha)
}

data class NoCustomAnimationSampleScreen(
override val index: Int
) : BaseSampleScreen("Default transition")

data class FadeAnimationSampleScreen(
override val index: Int
) : BaseSampleScreen("Fade transition"), ScreenTransition by FadeTransition()

data class SlideInVerticallyAnimationSampleScreen(
override val index: Int
) : BaseSampleScreen("slide in vertically transition"), ScreenTransition by SlideInVerticallyTransition(index)
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideIn
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOut
import androidx.compose.animation.slideOutVertically
import androidx.compose.ui.unit.IntOffset
import cafe.adriel.voyager.core.stack.StackEvent
import cafe.adriel.voyager.transitions.ScreenTransition
Expand Down Expand Up @@ -38,3 +40,26 @@ class SlideTransition : ScreenTransition {
}
}
}

class SlideInVerticallyTransition(val index: Int) : ScreenTransition {

override fun enter(lastEvent: StackEvent): EnterTransition {
return if (lastEvent == StackEvent.Pop) {
fadeIn(initialAlpha = 0.9f)
} else {
slideInVertically { it }
}
}

override fun exit(lastEvent: StackEvent): ExitTransition {
return if (lastEvent == StackEvent.Pop) {
slideOutVertically { it }
} else {
fadeOut(targetAlpha = 0.9f)
}
}

override fun zIndex(lastEvent: StackEvent): Float {
return if (lastEvent == StackEvent.Pop) (index).toFloat() else (index + 1).toFloat()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ class ScreenTransitionActivity : ComponentActivity() {
Text(text = "Fade")
}

Button(
onClick = { navigator.push(SlideInVerticallyAnimationSampleScreen(navigator.items.size)) },
modifier = Modifier.weight(1f)
) {
Text(text = "SlideInVertically")
}
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
horizontalArrangement = Arrangement.spacedBy(20.dp)
) {
Button(
onClick = { navigator.push(NoCustomAnimationSampleScreen(navigator.items.size)) },
modifier = Modifier.weight(1f)
Expand Down
1 change: 1 addition & 0 deletions voyager-transitions/api/android/voyager-transitions.api
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public final class cafe/adriel/voyager/transitions/ScaleTransitionKt {
public final class cafe/adriel/voyager/transitions/ScreenTransition$DefaultImpls {
public static fun enter (Lcafe/adriel/voyager/transitions/ScreenTransition;Lcafe/adriel/voyager/core/stack/StackEvent;)Landroidx/compose/animation/EnterTransition;
public static fun exit (Lcafe/adriel/voyager/transitions/ScreenTransition;Lcafe/adriel/voyager/core/stack/StackEvent;)Landroidx/compose/animation/ExitTransition;
public static fun zIndex (Lcafe/adriel/voyager/transitions/ScreenTransition;Lcafe/adriel/voyager/core/stack/StackEvent;)Ljava/lang/Float;
}

public final class cafe/adriel/voyager/transitions/ScreenTransitionKt {
Expand Down
1 change: 1 addition & 0 deletions voyager-transitions/api/desktop/voyager-transitions.api
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public final class cafe/adriel/voyager/transitions/ScaleTransitionKt {
public final class cafe/adriel/voyager/transitions/ScreenTransition$DefaultImpls {
public static fun enter (Lcafe/adriel/voyager/transitions/ScreenTransition;Lcafe/adriel/voyager/core/stack/StackEvent;)Landroidx/compose/animation/EnterTransition;
public static fun exit (Lcafe/adriel/voyager/transitions/ScreenTransition;Lcafe/adriel/voyager/core/stack/StackEvent;)Landroidx/compose/animation/ExitTransition;
public static fun zIndex (Lcafe/adriel/voyager/transitions/ScreenTransition;Lcafe/adriel/voyager/core/stack/StackEvent;)Ljava/lang/Float;
}

public final class cafe/adriel/voyager/transitions/ScreenTransitionKt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.core.annotation.ExperimentalVoyagerApi
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.Navigator

@Composable
Expand All @@ -33,13 +35,17 @@ public fun FadeTransition(
navigator: Navigator,
modifier: Modifier = Modifier,
animationSpec: FiniteAnimationSpec<Float> = spring(stiffness = Spring.StiffnessMediumLow),
contentAlignment: Alignment = Alignment.TopStart,
disposeScreenAfterTransitionEnd: Boolean = false,
contentKey: (Screen) -> Any = { it.key },
content: ScreenTransitionContent = { it.Content() }
) {
ScreenTransition(
navigator = navigator,
modifier = modifier,
contentAlignment = contentAlignment,
disposeScreenAfterTransitionEnd = disposeScreenAfterTransitionEnd,
contentKey = contentKey,
content = content,
transition = { fadeIn(animationSpec = animationSpec) togetherWith fadeOut(animationSpec = animationSpec) }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.animation.togetherWith
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.core.annotation.ExperimentalVoyagerApi
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.core.stack.StackEvent
import cafe.adriel.voyager.navigator.Navigator

Expand Down Expand Up @@ -37,13 +39,17 @@ public fun ScaleTransition(
navigator: Navigator,
modifier: Modifier = Modifier,
animationSpec: FiniteAnimationSpec<Float> = spring(stiffness = Spring.StiffnessMediumLow),
contentAlignment: Alignment = Alignment.TopStart,
disposeScreenAfterTransitionEnd: Boolean = false,
contentKey: (Screen) -> Any = { it.key },
content: ScreenTransitionContent = { it.Content() }
) {
ScreenTransition(
navigator = navigator,
modifier = modifier,
contentAlignment = contentAlignment,
disposeScreenAfterTransitionEnd = disposeScreenAfterTransitionEnd,
contentKey = contentKey,
content = content,
transition = {
val (initialScale, targetScale) = when (navigator.lastEvent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import androidx.compose.animation.ContentTransform
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.togetherWith
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.core.annotation.ExperimentalVoyagerApi
import cafe.adriel.voyager.core.screen.Screen
Expand All @@ -39,6 +39,14 @@ public interface ScreenTransition {
* @return ExitTransition or null when it should not define a transition for this screen.
*/
public fun exit(lastEvent: StackEvent): ExitTransition? = null

/**
* Defines the z-index for the Screen.
*
* @param lastEvent - lastEvent in the navigation stack.
* @return Float value for the z-index.
*/
public fun zIndex(lastEvent: StackEvent): Float? = null
}

public typealias ScreenTransitionContent = @Composable AnimatedVisibilityScope.(Screen) -> Unit
Expand All @@ -50,13 +58,17 @@ public fun ScreenTransition(
enterTransition: AnimatedContentTransitionScope<Screen>.() -> ContentTransform,
exitTransition: AnimatedContentTransitionScope<Screen>.() -> ContentTransform,
modifier: Modifier = Modifier,
contentAlignment: Alignment = Alignment.TopStart,
disposeScreenAfterTransitionEnd: Boolean = false,
contentKey: (Screen) -> Any = { it.key },
content: ScreenTransitionContent = { it.Content() }
) {
ScreenTransition(
navigator = navigator,
modifier = modifier,
contentAlignment = contentAlignment,
disposeScreenAfterTransitionEnd = disposeScreenAfterTransitionEnd,
contentKey = contentKey,
content = content,
transition = {
when (navigator.lastEvent) {
Expand All @@ -77,8 +89,12 @@ public fun ScreenTransition(
) {
ScreenTransition(
navigator = navigator,
enterTransition = enterTransition,
exitTransition = exitTransition,
transition = {
when (navigator.lastEvent) {
StackEvent.Pop -> exitTransition()
else -> enterTransition()
}
},
modifier = modifier,
content = content
)
Expand All @@ -90,18 +106,27 @@ public fun ScreenTransition(
navigator: Navigator,
defaultTransition: ScreenTransition,
modifier: Modifier = Modifier,
contentZIndex: Float = 0f,
contentAlignment: Alignment = Alignment.TopStart,
disposeScreenAfterTransitionEnd: Boolean = false,
contentKey: (Screen) -> Any = { it.key },
content: ScreenTransitionContent = { it.Content() }
) {
ScreenTransition(
navigator = navigator,
transition = {
val enter = defaultTransition.enter(navigator.lastEvent) ?: EnterTransition.None
val exit = defaultTransition.exit(navigator.lastEvent) ?: ExitTransition.None
enter togetherWith exit
ContentTransform(
targetContentEnter = enter,
initialContentExit = exit,
targetContentZIndex = contentZIndex
)
},
modifier = modifier,
contentAlignment = contentAlignment,
disposeScreenAfterTransitionEnd = disposeScreenAfterTransitionEnd,
contentKey = contentKey,
content = content
)
}
Expand Down Expand Up @@ -129,7 +154,9 @@ public fun ScreenTransition(
navigator: Navigator,
transition: AnimatedContentTransitionScope<Screen>.() -> ContentTransform,
modifier: Modifier = Modifier,
contentAlignment: Alignment = Alignment.TopStart,
disposeScreenAfterTransitionEnd: Boolean = false,
contentKey: (Screen) -> Any = { it.key },
content: ScreenTransitionContent = { it.Content() }
) {
val screenCandidatesToDispose = rememberSaveable(saver = screenCandidatesToDisposeSaver()) {
Expand Down Expand Up @@ -163,13 +190,18 @@ public fun ScreenTransition(
val screenExitTransition = sourceScreenTransition?.exit(navigator.lastEvent)
?: contentTransform.initialContentExit

val screenContentZIndex = sourceScreenTransition?.zIndex(navigator.lastEvent)
?: contentTransform.targetContentZIndex

ContentTransform(
screenEnterTransition,
screenExitTransition,
contentTransform.targetContentZIndex,
contentTransform.sizeTransform
targetContentEnter = screenEnterTransition,
initialContentExit = screenExitTransition,
targetContentZIndex = screenContentZIndex,
sizeTransform = contentTransform.sizeTransform
)
},
contentAlignment = contentAlignment,
contentKey = contentKey,
modifier = modifier
) { screen ->
if (this.transition.targetState == this.transition.currentState && disposeScreenAfterTransitionEnd) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.togetherWith
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.IntOffset
import cafe.adriel.voyager.core.annotation.ExperimentalVoyagerApi
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.core.stack.StackEvent
import cafe.adriel.voyager.navigator.Navigator

Expand Down Expand Up @@ -47,13 +49,17 @@ public fun SlideTransition(
stiffness = Spring.StiffnessMediumLow,
visibilityThreshold = IntOffset.VisibilityThreshold
),
contentAlignment: Alignment = Alignment.TopStart,
disposeScreenAfterTransitionEnd: Boolean = false,
contentKey: (Screen) -> Any = { it.key },
content: ScreenTransitionContent = { it.Content() }
) {
ScreenTransition(
navigator = navigator,
modifier = modifier,
contentAlignment = contentAlignment,
disposeScreenAfterTransitionEnd = disposeScreenAfterTransitionEnd,
contentKey = contentKey,
content = content,
transition = {
val (initialOffset, targetOffset) = when (navigator.lastEvent) {
Expand Down

0 comments on commit e14783e

Please sign in to comment.