Zoltan Demant
08/22/2022, 3:53 AMModifier.blur
seems like the way to go, but Im also trying to support this effect all the way down to API 21. Has anyone had any success with alternative approaches?Colton Idle
08/22/2022, 5:59 AMZoltan Demant
08/22/2022, 6:13 AMColton Idle
08/22/2022, 9:52 AMZoltan Demant
08/22/2022, 9:59 AMColton Idle
08/22/2022, 10:12 AMZoltan Demant
08/22/2022, 10:22 AMColton Idle
08/31/2022, 11:33 AMZoltan Demant
08/31/2022, 11:47 AM@Composable
fun Capture(
key: Int = currentCompositeKeyHash,
context: Context = LocalContext.current,
transformation: Transformation = NoTransformation,
content: @Composable () -> Unit,
onBitmapCaptured: (Bitmap) -> Unit,
) {
val cachedBitmap = BitmapCache[key]
if (cachedBitmap != null) {
onBitmapCaptured(cachedBitmap)
return
}
val scope = rememberCoroutineScope()
val view = remember(key) {
ComposeView(context).apply { visibility = INVISIBLE }
}
LaunchedEffect(view) {
<http://view.post|view.post> {
scope.launch {
val bitmap = withContext(Default) {
view.createTransformedBitmap(transformation)
}
BitmapCache[key] = bitmap
onBitmapCaptured(bitmap)
}
}
}
AndroidView(
factory = {
view.apply { setContent(content) }
},
)
}
var script: RenderScript? = null
var input: Allocation? = null
var output: Allocation? = null
var blur: ScriptIntrinsicBlur? = null
try {
script = RenderScript.create(context)
script.messageHandler = RSMessageHandler()
input = createFromBitmap(
script,
bitmap,
MIPMAP_NONE,
USAGE_SCRIPT,
)
output = createTyped(
script,
input.type,
)
blur = create(
script,
U8_4(script),
)
blur.setInput(input)
blur.setRadius(radius)
blur.forEach(output)
output.copyTo(bitmap)
} finally {
script?.destroy()
input?.destroy()
output?.destroy()
blur?.destroy()
}
return bitmap
@Composable
fun Capture(
key: Int = currentCompositeKeyHash,
transformation: Transformation = NoTransformation,
content: @Composable () -> Unit,
callback: (Bitmap) -> Unit,
) {
val cachedBitmap = BitmapCache[key]
if (cachedBitmap != null) {
callback(cachedBitmap)
return
}
val scope = rememberCoroutineScope()
AndroidView(
factory = { context ->
ComposeView(context).apply {
visibility = INVISIBLE
captureBitmap(
scope = scope,
transformation = transformation,
content = content,
callback = { bitmap ->
BitmapCache[key] = bitmap
callback(bitmap)
},
)
}
},
)
}
private inline fun ComposeView.captureBitmap(
scope: CoroutineScope,
transformation: Transformation,
noinline content: @Composable () -> Unit,
crossinline callback: (Bitmap) -> Unit,
) {
setContent(content)
val listener = object : OnGlobalLayoutListener {
override fun onGlobalLayout() {
viewTreeObserver.removeOnGlobalLayoutListener(this)
scope.launch {
val bitmap = withContext(Default) {
createTransformedBitmap(transformation)
}
callback(bitmap)
}
}
}
viewTreeObserver.addOnGlobalLayoutListener(listener)
}
private suspend fun View.createTransformedBitmap(
transformation: Transformation,
): Bitmap {
val bitmap = createBitmap(
width,
height,
ARGB_8888,
)
val canvas = Canvas(bitmap)
draw(canvas)
return transformation.transform(
context = context,
bitmap = bitmap,
)
}
Colton Idle
08/31/2022, 3:21 PMmgrazianodecastro
09/08/2022, 4:11 AMZoltan Demant
09/08/2022, 4:30 AMmgrazianodecastro
09/09/2022, 1:50 AM