-
Notifications
You must be signed in to change notification settings - Fork 173
Compose MotionLayout JSON Syntax
This is an early release of MotionLayout. Our first emphasis is on developing the JSON syntax. Eventually we will support direct implementation in Kotlin. The Functionality operates identically to the 2.1 MotionLayout equivalent.
{
Header:{}
Design:{}
Variables:{}
ConstraintSets:{}
Transitions: {
// Transition Named default (special name)
default:{
KeyFrames:{
KeyPositions: {}
KeyAttributes: {}
KeyCycles: {}
}
}
}
}
This allows you to export the current string for Realtime remote editing via Link
Header:{
exportAs: 'main screen'
}
This allows you to create widgets (currently only text and button)
Design: {
toto: {
type: 'button',
text: 'plop'
}
}
This allows you to define variables that can be used multiple times across the entire string.
Variables: {
simple1: 8
increment1 : { from: 90, step: 10 }
increment2 : { from: 1, to: 36, prefix: 'h' },
fromtag1: { tag: 'box' }
},
- simple1 can be used in many places and will be replaced by 8
- increment1 value will change (increase by 10) each time it is used (especially useful in combination with Generate: )
- increment2 will have the values h1 to h36
- fromtag1 will map to all ids of the views created with with a tag.
For example if composables were created like this:
for (i in 1..36) {
Box(modifier = Modifier
.layoutId("id$i", "box")
.background(colors[i % colors.size]))
}
fromtag1 will be [id1,id2,...id36]
Generate section can be used to generate a collection of Constraint objects when used with variables. For example:
{
Variables: {
angle: { from: 0, step: 10 },
rotation: { from: 'startRotation', step: 10 },
distance: 100,
mylist: { tag: 'box' }
},
Generate: {
mylist: {
width: 200,
height: 40,
circular: ['parent', 'angle', 'distance'],
pivotX: 0.1,
pivotY: 0.1,
translationX: 225,
rotationZ: 'rotation'
}
}
}
This (above) will generate a collection constraints for each Composable created with the tag 'box'. The will have circular constraints (typically circular:[viewid, angle, distance]) but the angle will be different for each widget created. The first starting at 'startRotation' (which is undefined at this point) When constructing the ConstraintSet overridVariables would have to contain startRotation:
var cs1 = ConstraintSet(baseConstraintSet, overrideVariables = "{ startRotation: 0 }")
var cs2 = ConstraintSet(baseConstraintSet, overrideVariables = "{ startRotation: 90 }")
Constructing the ConstraintSet without oveeridVariables will result in and exception
The pattern is typically
setId1:{ // setId1 is the name of the ConstraintSet equivalent to <ConstraintSet android:id="@id/setId1" ...>
widgetId1{ ...} // widgetId1 is the id of the widget equivalent of <Constraint android:id="@id/..." ...>
widgetId2{ ...}
widgetId3{ ...}
}
setId12:{
widgetId1{ ...}
widgetId2{ ...}
widgetId3{ ...}
}
}
Example:
ConstraintSets: {
start: {
a: {
width: 40,
height: 40,
start: ['parent', 'start', 16],
bottom: ['parent', 'bottom', 16]
}
},
end: {
a: {
width: 40,
height: 40,
end: ['parent', 'end', 16],
top: ['parent', 'top', 16]
}
}
}
Support the following key words
- width
- height
- start
- end
- top
- bottom
- left
- right
- center
- centerHorizontally
- centerVertically
- alpha
- scaleX
- scaleY
- translationX
- translationY
- translationZ
- pivotX
- pivotY
- rotationX
- rotationY
- rotationZ
- visibility (= visible, invisible, gone)
- custom - custom properties
For compose custom properties must be extracted and set manually. So for a typical custom property set:
custom: {
background: '#0000FF',
textColor: '#FFFFFF',
textSize: 12
}
You would need to set them using the below logic.
var properties = motionProperties("a")
Text(text = "Hello", modifier = Modifier
.layoutId(properties.value.id())
.background(properties.value.color("background"))
,color = properties.value.color("textColor")
,fontSize = properties.value.fontSize("textSize")
)
Transitions is a container for all transitions. Each Transition is given a name. The name "default" is special and defines the initial transition.
Transitions: {
default: {
from: 'start',
to: 'end',
pathMotionArc: 'startHorizontal',
KeyFrames: {
KeyPositions: [
{
target: ['a'],
frames: [25, 50, 75],
percentX: [0.4, 0.8, 0.1],
percentY: [0.4, 0.8, 0.3]
}
],
KeyCycles: [
{
target: ['a'],
frames: [0, 50, 100],
period: [0 , 2 , 0],
rotationX: [0, 45, 0],
rotationY: [0, 45, 0],
}
]
}
}
The above is a transition from ConstraintSet "start" to ConstraintSet "end" paths with move in an Arc (quarter ellipse) starting horizontally. It also contains Keframes of type keyCycle and KeyPosition.
We currently only support 3 types of keyFrames. All types of key frames will have the following:
- target - id's of the key widgets that these key positions apply
- frames - The position on the frames of each of the keys
For people familiar with MotionLayout in 2.x this is a more compact expression. For each target, for each frame a keyFrame is generated. i.e.
target: ['a', 'b'],
frames: [0, 50, 100],
// will generate 6 key frames
- KeyPosition - Manipulate the path of the view. KeyPosition Video
- KeyAttributes - Miniplate a view Transform and custom attributes. KeyAttributes Video
- KeyCycle - Produce repeating patterns.KeyCycle Video
- percentWidth
- percentHeight
- sizePercent
- percentX
- percentY
- frame - The widgets to transform
- target - the key frames
- curveFit - interpolate between points using linear interpolation or a monotonic spline
- alpha - how transparent the widget should be.
- rotationZ - post layout rotate the widget
- rotationX - post layout rotate about a horizontal axis
- rotationY - post layout rotate about a vertical axis
- pivotX - post layout the point around which to rotate
- pivotY - post layout the point around which to rotate
- pathRotate - The angle with respect to the path of the widget to rotate
- scaleX - post layout
- scaleY - post layout
- translationX - post layout move the widget to the right
- translationY - post layout move widget down
- translationZ - post layout move widget towards the viewer expanding its shadow
(Not implemented yet pivotTarget, easing, progress )
- offset - the center of the wave
- phase - the phase angle of the wave in this area
- period - the number of waves to generate in this area
- frame - The widgets to transform
- target - the key frames
- curveFit - interpolate between points using linear interpolation or a monotonic spline
- alpha - how transparent the widget should be.
- rotationZ - post layout rotate the widget
- rotationX - post layout rotate about a horizontal axis
- rotationY - post layout rotate about a vertical axis
- pivotX - post layout the point around which to rotate
- pivotY - post layout the point around which to rotate
- pathRotate - The angle with respect to the path of the widget to rotate
- scaleX - post layout
- scaleY - post layout
- translationX - post layout move the widget to the right
- translationY - post layout move widget down
- translationZ - post layout move widget towards the viewer expanding its shadow
(Not implemented yet pivotTarget, easing, progress ,waveShape )