Skip to content

Instantly share code, notes, and snippets.

@musenkishi
Created February 2, 2025 18:10
Show Gist options
  • Save musenkishi/d8cc1304aaedf64877f59ea204ad54a1 to your computer and use it in GitHub Desktop.
Save musenkishi/d8cc1304aaedf64877f59ea204ad54a1 to your computer and use it in GitHub Desktop.
Example code to use Rive animations as icons within interactive UI elements, like buttons
abstract class Artboard(val name: String) {
val stateMachine = "stateMachine"
}
@Composable
fun Example() {
val icon1 = RiveIconSet.RiveIcons.icon1Artboard
val myColor = MaterialTheme.colorScheme.onSurface
RiveView(
modifier = Modifier.size(32.dp),
resId = RiveIconSet.RiveIcons.resId,
artboardName = icon1.artboard.name,
stateMachineName = icon.artboard.stateMachine,
onUpdate = { riveView ->
icon1.setInputs(
view = riveView,
color = { myColor }
)
}
}
import android.annotation.SuppressLint
import android.content.Context
import android.view.MotionEvent
import app.rive.runtime.kotlin.RiveAnimationView
/**
* A custom [RiveAnimationView] that can optionally consume touch events.
*
* By default, [RiveAnimationView] consumes all touch events, which can interfere with
* its use within interactive UI components such as buttons. `PassthroughRiveView` allows
* developers to control whether touch events should be consumed by the view or passed through
* to other views.
*
* @param context The context the view is running in.
* @param consumeTouch If `true`, the view consumes touch events. If `false`, touch events
* are passed to other views. Defaults to `false`.
*/
@SuppressLint("ViewConstructor")
class PassthroughRiveView(context: Context, private val consumeTouch: Boolean = false) :
RiveAnimationView(context) {
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean {
return consumeTouch && super.onTouchEvent(event)
}
}
import androidx.compose.ui.graphics.ColorProducer
import app.rive.runtime.kotlin.RiveAnimationView
import com.musen.R
sealed class RiveIconSet() {
data object RiveIcons : RiveIconSet()
val resId = R.raw.icons // your .riv file
class Icon1 : Artboard("MyArtboardName") {
fun setInputs(
view: RiveAnimationView,
color: ColorProducer
) {
view.setNumberState(
stateMachineName = stateMachine,
inputName = "red",
value = color().red * 255
)
view.setNumberState(
stateMachineName = stateMachine,
inputName = "green",
value = color().green * 255
)
view.setNumberState(
stateMachineName = stateMachine,
inputName = "blue",
value = color().blue * 255
)
view.alpha = color().alpha
}
}
val icon1Artboard = Icon1()
}
import androidx.annotation.RawRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.viewinterop.AndroidView
import app.rive.runtime.kotlin.RiveAnimationView
import app.rive.runtime.kotlin.core.Alignment
import app.rive.runtime.kotlin.core.Fit
import com.musen.R
import com.musen.model.rive.PassthroughRiveView
@Composable
fun RiveView(
modifier: Modifier = Modifier,
@RawRes resId: Int,
fit: Fit = Fit.CONTAIN,
artboardName: String,
stateMachineName: String? = null,
allowTouch: Boolean = false,
onUpdate: (RiveAnimationView) -> Unit
) {
if (LocalInspectionMode.current) { // placeholder for previews
Box {
Image(
modifier = modifier,
painter = painterResource(R.drawable.ic_launcher_monochrome),
contentDescription = "RiveView Preview",
colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.primary)
)
}
} else {
AndroidView(
modifier = modifier,
factory = { context ->
PassthroughRiveView(context, consumeTouch = allowTouch).also {
it.setRiveResource(
resId = resId,
alignment = Alignment.CENTER,
artboardName = artboardName,
fit = fit,
stateMachineName = stateMachineName
)
}
},
update = { view ->
onUpdate(view)
}
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment