rive-app / rive-android

A runtime for interactive animations on Android
https://rive.app
MIT License
346 stars 31 forks source link

Android RiveView capture not working #333

Open blueparkyanadoocorp opened 1 month ago

blueparkyanadoocorp commented 1 month ago

Hello How do I Capture RiveView in Android?

Here is my code.

[Compose Button] @Composable fun MyRoomShareView( modifier: Modifier = Modifier, uiState: MyRoomUiState, onShare: (Uri) -> Unit = {}, ) { val context = LocalContext.current val coroutineScope = rememberCoroutineScope() Box( modifier = modifier .padding(top = 8.dp, start = 8.dp, end = 8.dp, bottom = 32.dp) ) { Column( modifier = modifier .fillMaxWidth() .wrapContentHeight() ) {

        val screenshotableComposable = screenshotableComposable(
            content = {
                MyRoomShareMyProfileView(
                    uiState = uiState
                )
            }
        )

        Box(modifier = Modifier.weight(1f, fill = true))

        MyTextButton(
            modifier = Modifier
                .fillMaxWidth(),
            text = stringResource(id = R.string.str_share_my_room),
            textColor = White,
            contentColor = Blue500,
            onClick = {
                Timber.d("onClick~~")
                    val captureBitmap = screenshotableComposable.invoke()
                    // Image Quality 80% 

                    val bmp = ImageUtils.compressBitmap(captureBitmap, ImageUtils.IMAGE_QUALITY)
                    val folder = FileUtils.getFolderPath(context, FileUtils.MY_FOLDER)
                    val newFile = ImageUtils.saveBitmapToJpg(bmp, folder, "capture_${
                        SystemClock.elapsedRealtime().toString().plus("_").plus(UUID.randomUUID().toString().uppercase(
                            Locale.getDefault()
                        ).replace("-", "_").plus(".jpg"))}", ImageUtils.IMAGE_QUALITY)

                    val selectedMediaUri = FileUtils.file2Uri(context, newFile)

                    Timber.d("newFile :  ${newFile.name}, ${newFile.path}")

                    Timber.d("uri = ${selectedMediaUri}")
                    onShare.invoke(selectedMediaUri)
            }
        )
    }
}

}

@Composable fun screenshotableComposable(content: @Composable () -> Unit): () -> Bitmap { val context = LocalContext.current val composeView = remember { ComposeView(context = context) } fun captureBitmap(): Bitmap = composeView.drawToBitmap() AndroidView( factory = { composeView.apply { setContent { content() } } }, modifier = Modifier .fillMaxWidth() .wrapContentHeight() // Make sure to set unbounded true to draw beyond screen area ) return ::captureBitmap }

Thank you

HayesGordon commented 1 month ago

Hi @blueparkyanadoocorp, I'm not familiar with an example for Android that does this, but one thing you can try to see if it works with your current implementation is to use the Canvas renderers (instead of Skia or Rive). See our docs on choosing a renderer.

mrrobot97 commented 1 week ago

RiveAnimationView is a TextureView so you can't get a capture by normal view's way. Instead you can use TextureView.getBitmap() which is more convenient.