Examples
Adding an Event Listener
Similar to the addEventListener() / removeEventListener() API for DOM elements, you’ll use the Rive instance’s on() / off() API to subscribe to Rive events from the rive object returned from the useRive hook. Simply supply the RiveEvent enum and a callback for the runtime to call at the appropriate moment any Rive event gets detected.Note: You must use the useRive() hook to subscribe to Rive events
Example Usage
import { useRive, EventType, RiveEventType } from '@rive-app/canvas';
import { useCallback, useEffect } from 'react';
const MyTextComponent = () => {
const {rive, RiveComponent} = useRive({
src: "/static-assets/star-rating.riv",
artboard: "my-artboard-name",
autoplay: true,
// automaticallyHandleEvents: true, // Automatically handle OpenUrl events
stateMachines: "State Machine 1",
});
const onRiveEventReceived = (riveEvent) => {
const eventData = riveEvent.data;
const eventProperties = eventData.properties;
if (eventData.type === RiveEventType.General) {
console.log("Event name", eventData.name);
// Added relevant metadata from the event
console.log("Rating", eventProperties.rating);
console.log("Message", eventProperties.message);
} else if (eventData.type === RiveEventType.OpenUrl) {
console.log("Event name", eventData.name);
// Handle OpenUrl event manually
window.location.href = data.url;
}
};
// Wait until the rive object is instantiated before adding the Rive
// event listener
useEffect(() => {
if (rive) {
rive.on(EventType.RiveEvent, onRiveEventReceived);
}
}, [rive]);
return (
<RiveComponent />
);
};
Subscribing to Events via State Machine Delegate
To subscribe to Rive events, implement the onRiveEventReceived protocol from StateMachineDelegate.@objc optional func onRiveEventReceived(onRiveEvent riveEvent: RiveEvent)This implementation may be invoked when a Rive event is fired from the render loop and provides a generic RiveEvent data type, of which you can type check to cast to a specific event for further parsing, such as a RiveGeneralEvent or a RiveOpenUrlEvent.For example:@objc func onRiveEventReceived(onRiveEvent riveEvent: RiveEvent) {
debugPrint("Event Name: \(riveEvent.name())")
debugPrint("Event Type: \(riveEvent.type())")
if let openUrlEvent = riveEvent as? RiveOpenUrlEvent {
// i.e., open the URL
} else if let generalEvent = riveEvent as? RiveGeneralEvent {
// i.e., print the string data provided in a Text widget
}
}
Note: Events of type RiveOpenUrlEvent will not automatically open links in the user’s preferred browser. You will need to add the logic to grab the url property of the riveEvent passed into the delegate and open the link.
Example Usageimport SwiftUI
import RiveRuntime
struct SwiftEvents: DismissableView {
var dismiss: () -> Void = {}
@StateObject private var rvm = RiveEventsVMExample()
var body: some View {
VStack {
rvm.view()
Text("Event Message")
.font(.headline)
.padding(.bottom, 10)
Text(rvm.eventText)
.padding()
.background(rvm.eventText.isEmpty ? Color.clear : Color.black)
.foregroundColor(.white)
.cornerRadius(10)
}
}
}
class RiveEventsVMExample: RiveViewModel {
@Published var eventText = ""
init() {
super.init(fileName: "rating_animation")
}
func view() -> some View {
return super.view().frame(width: 400, height: 400, alignment: .center)
}
// Subscribe to Rive events and this delegate will be invoked
@objc func onRiveEventReceived(onRiveEvent riveEvent: RiveEvent) {
if let openUrlEvent = riveEvent as? RiveOpenUrlEvent {
if let url = URL(string: openUrlEvent.url()) {
#if os(iOS)
UIApplication.shared.open(url)
#else
NSWorkspace.shared.open(url)
#endif
}
} else if let generalEvent = riveEvent as? RiveGeneralEvent {
let genEventProperties = generalEvent.properties();
if let msg = genEventProperties["message"] {
eventText = msg as! String
}
}
}
}
Adding an Event Listener
Use the addEventListener and removeEventListener on RiveAnimationView to subscribe/unsubscribe aRiveFileController.RiveEventListener.This listener receives either an OpenURLRiveEvent or GeneralRiveEvent of type RiveEvent./// Access the RiveAnimationView
private val yourRiveAnimationView: RiveAnimationView by lazy(LazyThreadSafetyMode.NONE) {
findViewById(R.id.your_animation_view)
}
...
/// Create a RiveEventListener
val eventListener = object : RiveFileController.RiveEventListener {
override fun notifyEvent(event: RiveEvent) {
when (event) {
is OpenURLRiveEvent -> {
Log.i("RiveEvent", "Open URL Rive event: ${event.url}")
}
is GeneralRiveEvent -> {
Log.i("RiveEvent", "General Rive event")
}
}
Log.i("RiveEvent", "name: ${event.name}")
Log.i("RiveEvent", "type: ${event.type}")
Log.i("RiveEvent", "properties: ${event.properties}")
// `data` contains all information in the event
Log.i("RiveEvent", "data: ${event.data}");
}
}
/// Attach the listener
yourRiveAnimationView.addEventListener(eventListener);
...
/// Remove when no longer needed
override fun onDestroy() {
yourRiveAnimationView.removeEventListener(eventListener);
super.onDestroy()
}
The Rive Android Runtime is executed on a separate thread. Any UI updates that are triggered from a Rive event will need to be manually marked to run on the UI thread using runOnUiThread. See examples below.
Opening a URL
Events of type OpenUrlRiveEvent will not automatically open links. The code needs to be added manually in your project.
The following is an example that demonstrates how to open a URL on Android when an OpenUrlRiveEvent is received:val eventListener = object : RiveFileController.RiveEventListener {
override fun notifyEvent(event: RiveEvent) {
when (event) {
is OpenURLRiveEvent -> {
runOnUiThread {
try {
val uri = Uri.parse(event.url);
val browserIntent =
Intent(Intent.ACTION_VIEW, uri)
startActivity(browserIntent)
} catch (e: Exception) {
Log.i("RiveEvent", "Not a valid URL ${event.url}")
}
}
}
}
}
}
yourRiveAnimationView.addEventListener(eventListener);
You can also access event.target to get the target destination of the URL, as set in the editor.Example
The following demonstrates how to update UI in response to some Rive event (named “StarRating”) that contains a custom number property (named “Rating”). Note the runOnUiThread:val eventListener = object : RiveFileController.RiveEventListener {
override fun notifyEvent(event: RiveEvent) {
when (event) {
is GeneralRiveEvent -> {
runOnUiThread {
// This event contains a number value with the name "rating"
// to indicate the star rating selected
if (event.name == "StarRating" && event.properties.containsKey("rating")) {
starRatingTextView.text = "Star rating: ${event.properties["rating"]}"
}
}
}
}
}
}
It’s possible to evaluate which event has come through by checking the name and type of event (GeneralRiveEvent vs OpenURLRiveEvent).By calling event.properties you’ll get a HashMap that contains any custom properties defined on the event.