Interactivity powered by state machines

Interactivity is currently in it’s early stages of developement and not production ready. Please be aware that this API will change. If your state machine is not working as expected please create an issue on Github.

Creation

Learn how to create dotLotties with state machines here.

Usage

The following example demonstrates how to use a state machine with a Lottie animation in a Composable function. The state machine is controlled by a DotLottieController, which is used to load the state machine, start and stop it, and post events to it. The controller also provides a listener for state machine events.

Exploding Pigeon example

@Composable
fun StateMachineExample() {
// Controller for the DotLottieAnimation composable
val controller = remember { DotLottieController() }
// Listener for the state machine events
val stateListener = remember {
object : StateMachineEventListener {
// Logs the transition from one state to another
override fun onTransition(previousState: String, newState: String) {
Log.i("DotLottie", "Transition: $previousState -> $newState")
}
// Logs when a state is exited
override fun onStateExit(leavingState: String) {
Log.i("DotLottie", "Exit: $leavingState")
}
// Logs when a state is entered
override fun onStateEntered(enteringState: String) {
Log.i("DotLottie", "Enter: $enteringState")
}
}
}
// Adds the state machine event listener to the controller
LaunchedEffect(UInt) {
controller.addStateMachineEventListener(stateListener)
}
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Row {
DotLottieAnimation(
source = DotLottieSource.Asset("exploding_pigeon.lottie"),
autoplay = true,
loop = false,
controller = controller,
)
}
Row {
Column {
// Button to load and start the state machine
Button(onClick = {
val result = controller.loadStateMachine("pigeon_fsm")
if (result) {
controller.startStateMachine()
}
}) {
Text(text = "sate machine")
}
// Button to post an "explosion" event to the state machine. You can also bind this to a gesture or other event.
Button(onClick = {
controller.postEvent(Event.String("explosion"))
}) {
Text(text = "Explosion")
}
// Button to stop the state machine
Button(onClick = {
controller.stopStateMachine()
}) {
Text(text = "Stop")
}
}
}
}
}

Exploding Pigeon state machine

{
"descriptor": { "id": "pigeon_fsm", "initial": 0 },
"states": [
{
"name": "pigeon",
"type": "PlaybackState",
"mode": "Forward",
"speed": 1,
"use_frame_interpolation": true,
"autoplay": true,
"loop": true,
"marker": "bird"
},
{
"name": "explosion",
"type": "PlaybackState",
"mode": "Forward",
"autoplay": true,
"speed": 0.5,
"loop": false,
"marker": "explosion"
},
{
"name": "feathers",
"type": "PlaybackState",
"autoplay": true,
"speed": 1,
"loop": false,
"marker": "feathers"
}
],
"transitions": [
{
"type": "Transition",
"from_state": 0,
"to_state": 1,
"string_event": { "value": "explosion" }
},
{
"type": "Transition",
"from_state": 1,
"to_state": 2,
"on_complete_event": {}
},
{
"type": "Transition",
"from_state": 2,
"to_state": 0,
"on_complete_event": {}
}
],
...
}

How it works

  • The state machine has three states: pigeon, explosion, and feathers.
  • The state machine starts in the pigeon state.
  • When the explosion event is posted to the state machine, it transitions to the explosion state.
  • When the explosion state completes, it transitions to the feathers state.
  • When the feathers state completes, it transitions back to the pigeon state.