View Models
View models describe a set of properties, but cannot themselves be used to get or set values - that is the role of view model instances. To begin, we need to get a reference to a particular view model. This can be done either by index, by name, or the default for a given artboard, and is done from the Rive file. The default option refers to the view model assigned to an artboard by the dropdown in the editor.- Compose
- Legacy
Unlike other runtimes, view models do not exist as a separate object in the Compose API. Instead, they are represented as a
ViewModelSource sealed class that forms half of a builder pattern used to create view model instances. See View Model Instances for details on the other half - creating instances.View Model Instances
Once we have a reference to a view model, it can be used to create an instance. When creating an instance, you have four options:-
Create a blank instance - Fill the properties of the created instance with default values as follows:
Type Value Number 0 String Empty string Boolean False Color 0xFF000000 Trigger Untriggered Enum The first value Image No image Artboard No artboard List Empty list Nested view model Null - Create the default instance - Use the instance labelled “Default” in the editor. Usually this is the one a designer intends as the primary one to be used at runtime.
- Create by index - Using the order returned when iterating over all available instances. Useful when creating multiple instances by iteration.
- Create by name - Use the editor’s instance name. Useful when creating a specific instance.
In some samples, due to the wordiness of “view model instance”, we use the abbreviation “VMI”, as well as “VM” for “view model”.
- Compose
- Legacy
See View Models for how to get a Additionally, you can reference a nested view model instance from within a parent instance using the
ViewModelSource to use below. With that, you can use the builder pattern to create a ViewModelInstanceSource, the second half. That source can then be passed to rememberViewModelInstance to create and remember the instance for the lifetime of the composition.Reference variant.Binding
The created instance can then be assigned to a state machine or artboard. This establishes the bindings set up at edit time. It is preferred to assign to a state machine, as this will automatically apply the instance to the artboard as well. Only assign to an artboard if you are not using a state machine, i.e. your file is static or uses linear animations.The initial values of the instance are not applied to their bound elements until the state machine or artboard advances.
- Compose
- Legacy
See the Compose data binding example.Binding to the state machine happens automatically when the
ViewModelInstance is passed to the Rive composable.Auto-Binding
Alternatively, you may prefer to use auto-binding. This will automatically bind the default view model of the artboard using the default instance to both the state machine and the artboard. The default view model is the one selected on the artboard in the editor dropdown. The default instance is the one marked “Default” in the editor.- Compose
- Legacy
Auto-binding does not exist in the Compose API due to the nature of composables. Since they are functions, it is difficult to get values out of them as compared to classes. Callbacks would require a null placeholder to remember the value before it has fired which creates more overhead than supplying the instance directly.The equivalent is to create a view model instance with no source. This will internally create the default artboard, the default view model for that artboard, and the default instance for that view model. You can then pass that into the
Rive composable.Properties
A property is a value that can be read, set, or observed on a view model instance. Properties can be of the following types:| Type | Supported |
|---|---|
| Floating point numbers | ✅ |
| Booleans | ✅ |
| Triggers | ✅ |
| Strings | ✅ |
| Enumerations | ✅ |
| Colors | ✅ |
| Nested View Models | ✅ |
| Lists | ✅ |
| Images | ✅ |
| Artboards | ✅ |
Listing Properties
Property descriptors can be inspected on a view model to discover at runtime which are available. These are not the mutable properties themselves though - once again those are on instances. These descriptors have a type and name.- Compose
- Legacy
Getting view model properties is a suspend operation, so it needs to be called from a coroutine scope such as
LaunchedEffect.Reading and Writing Properties
References to these properties can be retrieved by name or path. Some properties are mutable and have getters, setters, and observer operations for their values. Getting or observing the value will retrieve the latest value set on that property’s binding, as of the last state machine or artboard advance. Setting the value will update the value and all of its bound elements.After setting a property’s value, the changes will not apply to their bound elements until the state machine or artboard advances.
- Compose
- Legacy
Writing Values
The Compose API does not have explicit property objects. Instead, property values are set on theViewModelInstance directly using methods which take their path.Reading Values
Values are read throw a KotlinFlow which emits the latest value whenever it changes. You can collect this flow in a LaunchedEffect or convert it to a State using collectAsState() (or use collectAsStateWithLifecycle() to only collect during certain lifecycle states).To get the latest value once without observing, you can use the terminal first() operator.Nested Property Paths
View models can have properties of type view model, allowing for arbitrary nesting. You can chain property calls on each instance starting from the root until you get to the property of interest. Alternatively, you can do this through a path parameter, which is similar to a URI in that it is a forward slash delimited list of property names ending in the name of the property of interest.- Compose
- Legacy
Observability
You can observe changes over time to property values, either by using listeners or a platform equivalent method. Once observed, you will be notified when the property changes are applied by a state machine advance, whether that is a new value that has been explicitly set or if the value was updated as a result of a binding.- Compose
- Legacy
Observability is the default behavior when using the Compose API with Kotlin Flows. When you collect a property’s flow, you will receive updates whenever the property’s value changes.
Images
Image properties let you set and replace raster images at runtime, with each instance of the image managed independently. For example, you could build an avatar creator and dynamically update features — like swapping out a hat — by setting a view model’s image property.- Compose
- Legacy
See the Compose data binding images example.To set an image property, you need an If you want to gate the presentation of your Rive content until the image is loaded and only if both are successful, you can use the For more information on image assets, see Loading Assets.
ImageAsset, which can be created from rememberImage using a byte array. The below example loads from raw resources into a Result for convenience, but you should use the pattern most appropriate for your app.zip convenience function to combine multiple Result objects together.Lists
List properties let you manage a dynamic set of view model instances at runtime. For example, you can build a TODO app where users can add and remove tasks in a scrollable Layout. See the Editor section on creating data bound lists. A single list property can include different view model types, with each view model tied to its own Component, making it easy to populate a list with a varity of Component instances. With list properties, you can:- Add a new view model instance (optionally at an index)
- Remove an existing view model instance (optionally by index)
- Swap two view model instances by index
- Get the size of a list
- Compose
- Legacy
See the Compose data binding lists example.Due to the dynamic nature of lists, you may need to create items within a coroutine rather than ahead of time with
rememberViewModelInstance. Be aware that adding the same instance multiple times to a list will cause them all to share state, which may not be the desired behavior. Use the following pattern to create new instances as needed.Artboards
Artboard properties allows you to swap out entire components at runtime. This is useful for creating modular components that can be reused across different designs or applications, for example:- Creating a skinning system that supports a large number of variations, such as a character creator where you can swap out different body parts, clothing, and accessories.
- Creating a complex scene that is a composition of various artboards loaded from various different Rive files (drawn to a single canvas/texture/widget).
- Reducing the size (complexity) of a single Rive file by breaking it up into smaller components that can be loaded on demand and swapped in and out as needed.
- Compose
- Legacy
Enums
Enums properties come in two flavors: system and user-defined. In practice, you will not need to worry about the distinction, but just be aware that system enums are available in any Rive file that binds to an editor-defined enum set, representing options from the editor’s dropdowns, where user-defined enums are those defined by a designer in the editor. Enums are string typed. The Rive file contains a list of enums. Each enum in turn has a name and a list of strings.- Compose
- Legacy
Examples
- Compose
- Legacy
See the following examples: