Shared Elements¶
Circuit has an additional artifact for integrating Compose Shared Elements Transitions with Navigation and Overlays. Circuit Shared Elements are designed as a lightweight API to easily access the required SharedTransitionScope
and AnimatedVisibilityScope
directly in a Composable nested within a Screen
.
There are few core APIs for setting up and providing the required SharedTransitionScope
in order use shared elements.
- SharedElementTransitionLayout is the layout that creates and provides a
SharedElementTransitionScope
- SharedElementTransitionScope is a
SharedTransitionScope
which is required to use the shared element modifiers. TheSharedElementTransitionScope
also provides access to aAnimatedVisibilityScope
.
You can follow along with the tutorial to see how to use these APIs.
Usage¶
SharedElementTransitionLayout¶
Normally SharedElementTransitionLayout
should be setup around the root Circuit. It needs to be outside of a ContentWithOverlays
or NavigableCircuitContent
in order for the Overlay and Navigation AnimatedVisibilityScope
to be available.
setContent {
CircuitCompositionLocals(circuit) {
SharedElementTransitionLayout {
ContentWithOverlays { NavigableCircuitContent() }
}
}
}
A PreviewSharedElementTransitionLayout
is provided for use when using @Preview
for any Composable that has a SharedElementTransitionScope
.
@OptIn(ExperimentalSharedTransitionApi::class)
@Preview
@Composable
private fun PreviewShowAnimalPortrait() {
PreviewSharedElementTransitionLayout {
StarTheme { PetDetail(state = AnimalSuccessState, modifier = Modifier.fillMaxSize()) }
}
}
SharedElementTransitionScope¶
SharedElementTransitionScope
extends SharedTransitionScope
which is required to use the core shared elements API. The scope can be accessed using the SharedElementTransitionScope
Composable wherever the SharedTransitionScope
is needed, without having to explicitly pass it to a calling Composable.
Screen UI
@OptIn(ExperimentalSharedTransitionApi::class)
@CircuitInject(screen = HomeScreen::class)
@Composable
fun HomeContent(state: HomeScreen.State, modifier: Modifier = Modifier) =
SharedElementTransitionScope {
// Content here
}
Normal UI
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
private fun GridItem(animal: PetListAnimal, modifier: Modifier = Modifier) =
SharedElementTransitionScope {
// Content here
}
Shared elements also need an AnimatedVisibilityScope
in order to animate the shared Composable. Without having to explicitly pass the AnimatedVisibilityScope
to the Composable, SharedElementTransitionScope
has methods to access a AnimatedVisibilityScope
via an AnimatedScope key. This can be done with requireAnimatedScope
to require the AnimatedVisibilityScope
or with findAnimatedScope
for an optional AnimatedVisibilityScope
.
Box(
modifier =
Modifier.sharedElement(
state = rememberSharedContentState(key = ImageElementKey(id)),
animatedVisibilityScope = requireAnimatedScope(Navigation),
)
)
Box(
modifier =
Modifier.thenIfNotNull(findAnimatedScope(Overlay)) { animatedScope ->
sharedElement(
state = rememberSharedContentState(key = ImageElementKey(id)),
animatedVisibilityScope = animatedScope,
)
}
)
AnimatedScope¶
By default Circuit provides a Navigation
and Overlay
AnimatedVisibilityScope
when a SharedElementTransitionScope
is available and either NavigableCircuitContent
or ContentWithOverlays
has been used.
An AnimatedScope
can be provided using ProvideAnimatedTransitionScope
, including custom scopes. Doing so will make the AnimatedVisibilityScope
available to the SharedElementTransitionScope
inside the ProvideAnimatedTransitionScope
.
AnimatedContent(modifier = modifier, transitionSpec = transitionSpec()) { targetState ->
ProvideAnimatedTransitionScope(Navigation, this) {
AnimatedNavContent(targetState) { content(it) }
}
}
In Circuit the Navigation AnimatedScope
is setup using a ProvideAnimatedTransitionScope
. This is done with an implementation of NavDecoration
, AnimatedNavDecoration
. It takes an AnimatedNavDecorator
to customize the Screen animation without having to manually setup a AnimatedContent
and SharedElementTransitionScope
. An example of a custom AnimatedNavDecorator
can be seen with the AndroidPredictiveBackNavigationDecoration
in circuitx-gesture-navigation
.
Non-Circuit usage¶
Circuit Shared Elements should be usable without any other Circuit artifact. The setup of SharedElementTransitionLayout
is the same outside the root content, but a non-Circuit setup would require explicit use of ProvideAnimatedTransitionScope
to provide the desired AnimatedVisibilityScope
.