在 jetpack compose 中更新图像中的位图

Update bitmap in Image in jetpack compose

任务:我在设置网格后尝试模糊视图,其中的单元格具有不同的颜色(在 [=55= 中效果很好) ] SDK 31+)

情况:由于在android SDK 31以下无法使用compose中的模糊,(我正在使用Renderscript来模糊捕获的视图位图)

问题:我不确定处理完成后如何更新图像中的位图或add/remove合成中的图像

到目前为止我做了什么:

模糊 android SDK 31+

@Composable
fun PlaceHolder(viewModel: PlaceHolderViewModel) {

    val viewState by rememberFlowWithLifecycle(viewModel.state)
        .collectAsState(initial = PlaceHolderViewState.Empty)

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
        PlaceHolderBlurBelowSDK31(viewState = viewState)
    } else {
        PlaceHolder(viewState = viewState)
    }

}

/**
 * blur for compose is only available for android 31 and above devices.
 */
@Composable
private fun PlaceHolder(viewState: PlaceHolderViewState) = Box(
    modifier = Modifier.blur(radius = 60.dp)
) {
    PlaceHolderGrid(viewState = viewState)
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun PlaceHolderGrid(viewState: PlaceHolderViewState) {
    val size = max(viewState.placeHolderInfo.colors.size, 3)
    val cellHeight = viewState.placeHolderInfo.maxHeight / (size / 3)

    LazyVerticalGrid(cells = GridCells.Fixed(3)) {
        itemsIndexed(items = viewState.placeHolderInfo.colors) { i: Int, color: String ->
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(cellHeight.dp)
                    .background(color = color.getColor())
            )
        }
    }

}

这是我正在为 android 31 以下的 SDK 尝试的

@Composable
fun PlaceHolderBlurBelowSDK31(viewState: PlaceHolderViewState) {

    CaptureBitmap(content = {
        PlaceHolderGrid(viewState = viewState)
    }, laidOut = { bitmap ->

        if (bitmap != null && bitmap.width != 0 && bitmap.height != 0) {
            val painter = rememberAsyncImagePainter(ImageRequest.Builder(LocalContext.current)
                .data(data = bitmap)
                .apply(
                    block = {
                        scale(Scale.FILL)
                    }
                ).build())
            Logger.e("placeholder", "Image - " + System.currentTimeMillis())
            Image(
                painter = painter,
                modifier = Modifier
                    .wrapContentSize()
                    .padding(16.dp),
                colorFilter = ColorFilter.tint(Color.Red),
                contentScale = ContentScale.Crop,
                contentDescription = "logo"
            )
        }
    })

}

@Composable
fun CaptureBitmap(
    content: @Composable () -> Unit,
    laidOut: @Composable (Bitmap?) -> Unit
) {

    val context = LocalContext.current

    /**
     * ComposeView that would take composable as its content
     * Kept in remember so recomposition doesn't re-initialize it
     **/
    val composeView = remember { ComposeView(context) }

    /**
     * Callback function which could get latest image bitmap
     **/
    fun captureBitmap(): Bitmap? {
        return try {
            composeView.drawToBitmap()
        } catch (e: Exception) {
            null
        }
    }


    /** Use Native View inside Composable **/
    AndroidView(modifier = Modifier
        .onGloballyPositioned {
            Logger.e("placeholder", "onGloballyPositioned - " + System.currentTimeMillis())
            laidOut.invoke(captureBitmap())
        },
        factory = {
            ComposeView(it).apply {
                setContent {
                    Logger.e("placeholder", "setContent - " + System.currentTimeMillis())
                    content.invoke()
                }
            }
        }
    )

}


需要位图方面的帮助才能更新图像。我知道它需要从 @Composable 作用域或函数中调用。

laidOut.invoke(captureBitmap())

我试过了

val bitmap: MutableState<Bitmap?> = mutableStateOf(null)
bitmap.value = captureBitmap()

但是,我没有取得任何进展。 请帮忙。

网格:

模糊:

在 Compose 中,当您需要更新视图时,任何此类情况都可以通过状态解决。创建可选位图类型的可变状态,更新它并显示它不是 null:

fun captureBitmap(): Bitmap? {
    return try {
        composeView.drawToBitmap()
    } catch (e: Exception) {
        null
    }
}

val (bitmap, updateBitmap) = remember { mutableStateOf<Bitmap?>(null) }

/** Use Native View inside Composable **/
AndroidView(modifier = Modifier
    .onGloballyPositioned {
        Logger.e("placeholder", "onGloballyPositioned - " + System.currentTimeMillis())
        updateBitmap(captureBitmap())
    },
    // ..
)


if (bitmap != null) {
    laidOut(bitmap)
}

我建议您查看 Compose documentation, including this youtube video 中的状态,它解释了基本原理。