Skip to content

Commit

Permalink
feat: added onStop callback for android (#7)
Browse files Browse the repository at this point in the history
* feat: added onStop callback for android

* fix: prevented onPlay event after reset

Co-authored-by: TMaszko <tomasz.krzyzowski@callstack.com>
  • Loading branch information
MrMuzyk and TMaszko authored May 11, 2021
1 parent d39e46c commit 21885ed
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 11 deletions.
33 changes: 24 additions & 9 deletions android/src/main/java/com/rivereactnative/RiveReactNativeView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,20 @@ import java.net.URL

class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout(context), LifecycleEventListener {
private var riveAnimationView: RiveAnimationView
private var resId: Int = -1
private val httpClient = ViewModelProvider(context.currentActivity as ViewModelStoreOwner).get(HttpClient::class.java)

enum class Events(private val mName: String) {
PLAY("onPlay"),
PAUSE("onPause");
PAUSE("onPause"),
STOP("onStop");

override fun toString(): String {
return mName
}
}



init {
context.addLifecycleEventListener(this)
riveAnimationView = RiveAnimationView(context)
Expand Down Expand Up @@ -64,7 +65,12 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout
}

override fun notifyStop(animation: PlayableInstance) {
//TODO("Not yet implemented")
if (animation is LinearAnimationInstance) {
onStop(animation.animation.name)
}
if (animation is StateMachineInstance) {
onStop(animation.stateMachine.name, true)
}
}

}
Expand Down Expand Up @@ -92,6 +98,16 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout
reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, Events.PAUSE.toString(), data)
}

fun onStop(animationName: String, isStateMachine: Boolean = false) {
val reactContext = context as ReactContext

val data = Arguments.createMap()
data.putString("animationName", animationName)
data.putBoolean("isStateMachine", isStateMachine)

reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, Events.STOP.toString(), data)
}

fun play() {
riveAnimationView.play()
}
Expand All @@ -101,13 +117,12 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout
}

fun stop() {
riveAnimationView.reset()
riveAnimationView.stop()
riveAnimationView.setRiveResource(resId, autoplay = false)
}

fun setResourceName(resourceName: String) {
val (propsFit, propsAlignment) = Pair(riveAnimationView.fit, riveAnimationView.alignment)
val resId = resources.getIdentifier(resourceName, "raw", context.packageName)
resId = resources.getIdentifier(resourceName, "raw", context.packageName)

riveAnimationView.setRiveResource(resId, fit = propsFit, alignment = propsAlignment)
}
Expand All @@ -125,7 +140,7 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout
fun setUrl(url: String) {
httpClient.byteLiveData.observe(context.currentActivity as LifecycleOwner,
Observer { bytes ->
// Pass the Rive file bytes to the animation view
// Pass the Rive file bytes to the animation view
riveAnimationView.setRiveBytes(
bytes,
// Fit the animation to the cover the entire view
Expand All @@ -148,11 +163,11 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout
}
}

class HttpClient: ViewModel() {
class HttpClient : ViewModel() {
var byteLiveData = MutableLiveData<ByteArray>()

fun fetchUrl(url: String) {
viewModelScope.launch{
viewModelScope.launch {
withContext(Dispatchers.IO) {
fetchAsync(url)
}
Expand Down
11 changes: 9 additions & 2 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,17 @@ export default function App() {
onPause={(animationName, isStateMachine) => {
console.log('paused animation name :', animationName, isStateMachine);
}}
onStop={(animationName, isStateMachine) => {
console.log(
'stopped animation name :',
animationName,
isStateMachine
);
}}
style={styles.box}
fit={Fit.ScaleDown}
// resourceName={Platform.OS === 'android' ? 'flying_car' : 'bird'}
url={'https://cdn.rive.app/animations/juice_v7.riv'}
resourceName={Platform.OS === 'android' ? 'flying_car' : 'bird'}
// url={'https://cdn.rive.app/animations/juice_v7.riv'}
/>
<View style={styles.wrapper}>
<TouchableOpacity onPress={toggleAnimation}>
Expand Down
21 changes: 21 additions & 0 deletions src/Rive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ type RiveProps = {
isStateMachine: boolean;
}>
) => void;
onStop?: (
event: NativeSyntheticEvent<{
animationName: string;
isStateMachine: boolean;
}>
) => void;
fit: Fit;
alignment: Alignment;
ref: any;
Expand All @@ -38,6 +44,7 @@ const VIEW_NAME = 'RiveReactNativeView';
type Props = {
onPlay?: (animationName: string, isStateMachine: boolean) => void;
onPause?: (animationName: string, isStateMachine: boolean) => void;
onStop?: (animationName: string, isStateMachine: boolean) => void;
fit?: Fit;
style?: ViewStyle;
testID?: string;
Expand All @@ -51,6 +58,7 @@ const RiveContainer = React.forwardRef<RiveRef, Props>(
{
onPlay,
onPause,
onStop,
style,
resourceName,
url,
Expand Down Expand Up @@ -87,6 +95,18 @@ const RiveContainer = React.forwardRef<RiveRef, Props>(
[onPause]
);

const onStopHandler = useCallback(
(
event: NativeSyntheticEvent<{
animationName: string;
isStateMachine: boolean;
}>
) => {
const { animationName, isStateMachine } = event.nativeEvent;
onStop?.(animationName, isStateMachine);
},
[onStop]
);
const play = useCallback(() => {
UIManager.dispatchViewManagerCommand(
findNodeHandle(riveRef.current),
Expand Down Expand Up @@ -130,6 +150,7 @@ const RiveContainer = React.forwardRef<RiveRef, Props>(
url={url}
onPlay={onPlayHandler}
onPause={onPauseHandler}
onStop={onStopHandler}
alignment={alignment}
/>
);
Expand Down

0 comments on commit 21885ed

Please sign in to comment.