This repository was archived by the owner on Dec 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 173
Introduction to MotionLayout in Compose
John Hoford edited this page Jul 30, 2021
·
8 revisions
MotionLayout's core engine allows you to interpolate between two constraintSet With Transitions and keyframes controlling the transitions.
<SideNote:
The full MotionLayout has many features (See ConstraintLayout 2.1)
The first release of MotionLayout in ConstraintLayoutCompose 1.0 focuses on a limited subset using the json syntax.
The hope is that users will provide feedback to allow us to tailor the API to developer needs.
MotionLayout for Compose takes on of:
- Two ConstraintsSet (start & end), a Transition, and progress
- A MotionScene and progress
See Introduction to ConstraintLayout for more details on ConstraintSets
fun MotionLayout(
start: ConstraintSet,
end: ConstraintSet,
transition: androidx.constraintlayout.compose.Transition? = null,
progress: Float,
debug: EnumSet<MotionLayoutDebugFlags> = EnumSet.of(MotionLayoutDebugFlags.NONE),
modifier: Modifier = Modifier,
optimizationLevel: Int = Optimizer.OPTIMIZATION_STANDARD,
crossinline content: @Composable MotionLayoutScope.() -> Unit
) {}
fun MotionLayout(
motionScene: MotionScene,
progress: Float,
debug: EnumSet<MotionLayoutDebugFlags> = EnumSet.of(MotionLayoutDebugFlags.NONE),
modifier: Modifier = Modifier,
optimizationLevel: Int = Optimizer.OPTIMIZATION_STANDARD,
crossinline content: @Composable() (MotionLayoutScope.() -> Unit),
) {}
Currently Transition Only supports a Transition String
e.g:
transition = Transition("""
{
KeyFrames: {
KeyPositions: [
{
target: ['a'],
frames: [50],
percentX: [0.8],
percentY: [0.8]
}
]
}
}
Details on Transitions in json
Currently MotionScene Only supports a json syntax MotionScene JSON syntax
@Preview(group = "motion8")
@Composable
public fun AttributesRotationXY() {
var animateToEnd by remember { mutableStateOf(false) }
val progress by animateFloatAsState(
targetValue = if (animateToEnd) 1f else 0f,
animationSpec = tween(6000)
)
Column {
MotionLayout(
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
.background(Color.White),
motionScene = MotionScene("""{
ConstraintSets: { // all ConstraintSets
start: { // constraint set id = "start"
a: { // Constraint for widget id='a'
width: 40,
height: 40,
start: ['parent', 'start', 16],
bottom: ['parent', 'bottom', 16]
}
},
end: { // constraint set id = "start"
a: {
width: 40,
height: 40,
//rotationZ: 390,
end: ['parent', 'end', 16],
top: ['parent', 'top', 16]
}
}
},
Transitions: { // All Transitions in here
default: { // transition named 'default'
from: 'start', // go from Transition "start"
to: 'end', // go to Transition "end"
pathMotionArc: 'startHorizontal', // move in arc
KeyFrames: { // All keyframes go here
KeyAttributes: [ // keyAttributes key frames go here
{
target: ['a'], // This keyAttributes group target id "a"
frames: [25,50,75], // 3 points on progress 25% , 50% and 75%
rotationX: [0, 45, 60], // the rotationX angles are a spline from 0,0,45,60,0
rotationY: [60, 45, 0], // the rotationX angles are a spline from 0,60,45,0,0
}
]
}
}
}
}"""),
debug = EnumSet.of(MotionLayoutDebugFlags.SHOW_ALL),
progress = progress) {
Box(modifier = Modifier
.layoutId("a")
.background(Color.Red))
}
Button(onClick = { animateToEnd = !animateToEnd }) {
Text(text = "Run")
}
}
}