diff --git a/android/build.gradle b/android/build.gradle index 90ddfd2..83a10e5 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -135,7 +135,7 @@ dependencies { implementation 'androidx.core:core-ktx:1.10.0' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1' - implementation 'app.rive:rive-android:8.2.1' + implementation 'app.rive:rive-android:8.4.0' implementation "androidx.startup:startup-runtime:1.1.1" implementation 'com.android.volley:volley:1.2.0' } diff --git a/android/src/main/java/com/rivereactnative/RiveReactNativeView.kt b/android/src/main/java/com/rivereactnative/RiveReactNativeView.kt index 2cf2a6e..25a48d9 100644 --- a/android/src/main/java/com/rivereactnative/RiveReactNativeView.kt +++ b/android/src/main/java/com/rivereactnative/RiveReactNativeView.kt @@ -4,7 +4,6 @@ import android.widget.FrameLayout import app.rive.runtime.kotlin.PointerEvents import app.rive.runtime.kotlin.RiveAnimationView import app.rive.runtime.kotlin.controllers.RiveFileController -import app.rive.runtime.kotlin.RiveArtboardRenderer import app.rive.runtime.kotlin.core.* import app.rive.runtime.kotlin.core.errors.* import com.android.volley.NetworkResponse @@ -13,14 +12,14 @@ import com.android.volley.Request import com.android.volley.Response import com.android.volley.toolbox.HttpHeaderParser import com.android.volley.toolbox.Volley -import com.facebook.react.uimanager.events.RCTEventEmitter import com.facebook.react.bridge.Arguments +import com.facebook.react.bridge.WritableMap import com.facebook.react.bridge.ReactContext import com.facebook.react.bridge.ReadableArray import com.facebook.react.modules.core.ExceptionsManagerModule import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.events.RCTEventEmitter import java.io.UnsupportedEncodingException -import kotlin.IllegalStateException class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout(context) { @@ -43,6 +42,7 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout STOP("onStop"), LOOP_END("onLoopEnd"), STATE_CHANGED("onStateChanged"), + RIVE_EVENT("onRiveEventReceived"), ERROR("onError"); override fun toString(): String { @@ -92,7 +92,18 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout } } + + val eventListener = object : RiveFileController.RiveEventListener { + override fun notifyEvent(event: RiveEvent) { + when (event) { + is RiveGeneralEvent -> onRiveEventReceived(event as RiveGeneralEvent) + is RiveOpenURLEvent -> onRiveEventReceived(event as RiveOpenURLEvent) + } + } + } + riveAnimationView.registerListener(listener) + riveAnimationView.addEventListener(eventListener) autoplay = false addView(riveAnimationView) } @@ -146,6 +157,45 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, Events.STATE_CHANGED.toString(), data) } + private fun convertHashMapToWritableMap(hashMap: HashMap): WritableMap { + val writableMap = Arguments.createMap() + + for ((key, value) in hashMap) { + when (value) { + is String -> writableMap.putString(key, value) + is Int -> writableMap.putInt(key, value) + is Float -> writableMap.putDouble(key, value.toDouble()) + is Double -> writableMap.putDouble(key, value) + is Boolean -> writableMap.putBoolean(key, value) + } + } + + return writableMap + } + + fun onRiveEventReceived(event: RiveEvent) { + val reactContext = context as ReactContext + val topLevelDict = Arguments.createMap() + + val eventProperties = Arguments.createMap().apply { + putString("name", event.name) + putDouble("delay", event.delay.toDouble()) + putMap("properties", convertHashMapToWritableMap(event.properties)) + } + + if (event is RiveOpenURLEvent) { + eventProperties.putString("url", event.url) + eventProperties.putString("target", event.target) + } + + topLevelDict.putMap( + "riveEvent", + eventProperties + ) + + reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, Events.RIVE_EVENT.toString(), topLevelDict) + } + fun play(animationName: String, rnLoopMode: RNLoopMode, rnDirection: RNDirection, isStateMachine: Boolean) { val loop = RNLoopMode.mapToRiveLoop(rnLoopMode) val direction = RNDirection.mapToRiveDirection(rnDirection) diff --git a/example/android/app/src/main/res/raw/rating.riv b/example/android/app/src/main/res/raw/rating.riv new file mode 100644 index 0000000..330f7e9 Binary files /dev/null and b/example/android/app/src/main/res/raw/rating.riv differ