Reputation: 626
I am trying to convert all the content of a LazyColumn to bitmap, and then export it to a pdf file.
I did find this library to take screenshots of what is showing but not for all the content. Content that was not showing is not included. So I also try to draw canvas instead, but we can not apply all styles of the content (like a markdown, custom background,...) So I am thinking that we can have a custom native Android View, it may be possible to do it, but I can't find a way to pass a composable into it.
So anyone done that before or has a solution for this?
Edit 1: I did try to use draw content in compose graphics alpha-02, but the content in the LazyColumn was unable to scroll:
onDrawWithContent {
val pictureCanvas = Canvas(picture.beginRecording(width, height))
draw(this, this.layoutDirection, pictureCanvas, this.size) {
////
}
picture.endRecording()
drawIntoCanvas { canvas -> canvas.nativeCanvas.drawPicture(picture) }
}
Upvotes: 1
Views: 6477
Reputation: 1
.drawWithCache {
if (isDownloading) {
onDrawWithContent {
graphicsLayer.record {
[email protected]()
}
drawLayer(graphicsLayer)
coroutineScope?.launch {
val bitmap = graphicsLayer.toImageBitmap()
onImageDrawn(bitmap.asAndroidBitmap())
}
}
} else {
onDrawWithContent {
drawContent()
}
}
}
Upvotes: 0
Reputation: 4206
I had the same requirement like you and wanted to be able to achieve capturing all screen. So I was able to achieve this inside a scrollable view with Capturable
The component which needs to be captured should be placed inside Capturable composable as follows:
@Composable
fun TicketScreen() {
// I was able to capture the full width of the composable which was not visible on the screen with a scroll modifier on top of the Capturable for example:
Column(modifier = Modifier.horizontalScroll(rememberScrollState())) {
Capturable(
modifier = Modifier,
controller = controller,
onCaptured = { bitmap, error ->
if (state.printVides) {
onEvent(ScanPrintEvent.SetImageBitmapVides(bitmap?.asAndroidBitmap()))
} else {
onEvent(ScanPrintEvent.SetImageBitmapNormal(bitmap?.asAndroidBitmap()))
}
}
) {
YourComposable()
}
}
}
Upvotes: 0
Reputation: 3242
Steps to Export Bitmaps
Use drawIntoCanvas
Method and delegate to
android.graphics.Picture
class.Picture
to Local Storage.First Thing First Add The Latest Release Of Compose Dependency1.6.0-alpha03 or new
implementation "androidx.compose.ui:ui:1.6.0-alpha03"
Modifier.drawWithCache
keeps the objects that are created inside of it cached. The objects are cached as long as the size of the drawing area is the same, or any state objects that are read have not changed. This modifier is useful for improving the performance of drawing calls as it avoids the need to reallocate objects (such as: Brush, Shader, Path etc.) that are created on the draw.
val picture = remember { Picture() }
Column(
modifier = Modifier
.padding(padding)
.fillMaxSize()
.drawWithCache {
// Example that shows how to redirect rendering to an Android Picture and then
// draw the picture into the original destination
val width = this.size.width.toInt()
val height = this.size.height.toInt()
onDrawWithContent {
val pictureCanvas =
androidx.compose.ui.graphics.Canvas(
picture.beginRecording(
width,
height
)
)
draw(this, this.layoutDirection, pictureCanvas, this.size) {
[email protected]()
}
picture.endRecording()
drawIntoCanvas { canvas -> canvas.nativeCanvas.drawPicture(picture) }
}
}
) {
ScreenContentToCapture()
}
After drawing the cache into Picture
. You can use Picture
an object to get the bitmap and export them to Local storage.
Saving the Image
We will use Picture
Object to capture the image and draw it into canvas and save that Bitmap
to Local storage using the FileWriter
.
private fun createBitmapFromPicture(picture: Picture): Bitmap {
val bitmap = Bitmap.createBitmap(
picture.width,
picture.height,
Bitmap.Config.ARGB_8888
)
val canvas = android.graphics.Canvas(bitmap)
canvas.drawColor(android.graphics.Color.WHITE)
canvas.drawPicture(picture)
return bitmap
}
private suspend fun Bitmap.saveToDisk(context: Context): Uri {
val file = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"screenshot-${System.currentTimeMillis()}.png"
)
file.writeBitmap(this, Bitmap.CompressFormat.PNG, 100)
return scanFilePath(context, file.path) ?: throw Exception("File could not be saved")
}
private fun File.writeBitmap(bitmap: Bitmap, format: Bitmap.CompressFormat, quality: Int) {
outputStream().use { out ->
bitmap.compress(format, quality, out)
out.flush()
}
}
Here you can refer complete code
https://gist.github.com/chiragthummar/35aa1d15882c4d5a105a3f89be821214
Upvotes: 7