I'm creating an AnimatedVisibility-like API that operates on a Bitmap of the content for enter-exit transitions. I'm using the recommended way to draw a composable's content into a bitmap.
Basically when the visible state changes from true to false, I want to obtain a bitmap of the last drawn frame and discard the composable, seamlessly swapping it for the bitmap. And when the visible state changes from false to true, I want to obtain a bitmap of the frame that would be drawn without actually drawing it to the screen, again, seamlessly swapping the bitmap for the actual content.
@Composable fun SomeAnimatedVisibility( visible: Boolean, modifier: Modifier = Modifier, // ... content: @Composable () -> Unit ) { val graphicsLayer = rememberGraphicsLayer() var bounds by remember { mutableStateOf(Rect.Zero) } LaunchedEffect(visible) { if (graphicsLayer.size.toSize() == Size.Zero) return@LaunchedEffect val bitmap = graphicsLayer.toImageBitmap().asAndroidBitmap() .copy(Bitmap.Config.ARGB_8888, false) // Do something cool with the bitmap } Layout( content = content, modifier = modifier .drawWithContent { graphicsLayer.record { [email protected]() } if (visible) { drawLayer(graphicsLayer) } } .onGloballyPositioned { bounds = it.boundsInRoot() }, measurePolicy = { measurables, constraints -> if (!visible) { return@Layout layout(0, 0) {} } val placeables = measurables.fastMap { it.measure(constraints) } val maxWidth: Int = placeables.fastMaxBy { it.width }?.width ?: 0 val maxHeight = placeables.fastMaxBy { it.height }?.height ?: 0 layout(maxWidth, maxHeight) { placeables.fastForEach { it.place(0, 0) } } } ) } The issue I'm facing is that I necessarily need the content to be drawn at least once to obtain a bitmap, and if my composable is initially composed with visible=false, the user does not expect it to be drawn or have any size. Moreover, even if it was initially visible, and we have a saved bitmap, the state with which the content will be drawn may have already changed, and the saved bitmap may not be representative of the actual content, which will be visible when swapping the bitmap to the content.
I also tried rendering a ComposeView into a bitmap to bypass the visible composition entirely, but it always measures with 0 width and height.
So, the question from the title stands: is it possible to draw a composable into canvas out-of-composition, or are there any tricks for my particular case that I'm not seeing?