Code
Orbitary – Jetpack Compose animation library

Jetpack Compose animation library that allows you to implement animations such as shared element transition.
Orbitary usage
You can implement three kinds of animations with Orbitary: Movement, Transformation, and Shared Element Transition. Basically, you can run animation with Orbitary
Composable function, which provides OrbitaryScope
that allows you to create animations.
Transformation
The example below shows how to implement resizing animation with the animateTransformation
extension of the OrbitaryScope
. The rememberContentWithOrbitaryScope
allows you to create custom animations such as animateTransformation
on the OrbitaryScope
. You can apply the animateTransformation
animation to specific Composables and customize its AnimationSpec
as seen the below:
val transformationSpec = SpringSpec<IntSize>(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = 200f
)
var isTransformed by rememberSaveable { mutableStateOf(false) }
val poster = rememberContentWithOrbitaryScope {
GlideImage(
modifier = if (isTransformed) {
Modifier.size(300.dp, 620.dp)
} else {
Modifier.size(100.dp, 220.dp)
}.animateTransformation(this, transformationSpec),
imageModel = ItemUtils.urls[0],
contentScale = ContentScale.Fit
)
}
Orbitary(
modifier = Modifier
.clickable { isTransformed = !isTransformed }
) {
Column(
Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
poster()
}
}
Movement
The example below shows how to implement movement animation with the animateMovement
extension of the OrbitaryScope
. The rememberContentWithOrbitaryScope
allows you to create custom animations such as animateMovement
on the OrbitaryScope
. You can apply the animateMovement
animation to specific Composables and customize its AnimationSpec
as seen the below:
val movementSpec = SpringSpec<IntOffset>(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = 200f
)
var isTransformed by rememberSaveable { mutableStateOf(false) }
val poster = rememberContentWithOrbitaryScope {
GlideImage(
modifier = if (isTransformed) {
Modifier.size(360.dp, 620.dp)
} else {
Modifier.size(130.dp, 220.dp)
}.animateMovement(this, movementSpec),
imageModel = ItemUtils.urls[3],
contentScale = ContentScale.Fit
)
}
Orbitary(
modifier = Modifier
.clickable { isTransformed = !isTransformed }
) {
if (isTransformed) {
Column(
Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
poster()
}
} else {
Column(
Modifier
.fillMaxSize()
.padding(20.dp),
horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.Bottom
) {
poster()
}
}
}
Shared Element Transition
The example below shows how to implement shared element transition with the animateSharedElementTransition
extension of the OrbitaryScope
. The rememberContentWithOrbitaryScope
allows you to create custom animations such as animateSharedElementTransition
on the OrbitaryScope
. You can apply the animateSharedElementTransition
animation to specific Composables and customize its AnimationSpec
. Also, you can set the different AnimationSpec
s for the movement and transformation as seen the below:
@Composable
private fun OrbiraySharedElementTransitionExample() {
var isTransformed by rememberSaveable { mutableStateOf(false) }
val item = MockUtils.getMockPosters()[3]
val poster = rememberContentWithOrbitaryScope {
GlideImage(
modifier = if (isTransformed) {
Modifier.fillMaxSize()
} else {
Modifier.size(130.dp, 220.dp)
}.animateSharedElementTransition(
this,
SpringSpec(stiffness = 500f),
SpringSpec(stiffness = 500f)
),
imageModel = item.poster,
contentScale = ContentScale.Fit
)
}
Orbitary(
modifier = Modifier
.clickable { isTransformed = !isTransformed }
) {
if (isTransformed) {
PosterDetails(
poster = item,
sharedElementContent = { poster() },
pressOnBack = {}
)
} else {
Column(
Modifier
.fillMaxSize()
.padding(20.dp),
horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.Bottom
) {
poster()
}
}
}
}
Note: LookaheadLayout is a very experimental API, so measuring complex Composables might throw exceptions.
Shared Element Transition with Multiple Items
The example below shows how to implement shared element transition with multipe items. The basic concept of the usage is the same as the Shared Element Transition example.
var isTransformed by rememberSaveable { mutableStateOf(false) }
val items = rememberContentWithOrbitaryScope {
ItemUtils.urls.forEach { url ->
GlideImage(
modifier = if (isTransformed) {
Modifier.size(140.dp, 180.dp)
} else {
Modifier.size(100.dp, 220.dp)
}
.animateSharedElementTransition(this, movementSpec, transformationSpec)
.padding(8.dp),
imageModel = url,
contentScale = ContentScale.Fit
)
}
}
Orbitary(
modifier = Modifier
.fillMaxSize()
.clickable { isTransformed = !isTransformed },
isTransformed = isTransformed,
onStartContent = {
Column(
Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
items()
}
},
onTransformedContent = {
Row(
verticalAlignment = Alignment.CenterVertically
) { items() }
}
)
