Created
February 2, 2025 18:10
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
abstract class Artboard(val name: String) { | |
val stateMachine = "stateMachine" | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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 } | |
) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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