Quiero tomar una captura de pantalla de una función componible específica en Jetpack Compose. ¿Cómo puedo hacer esto? Por favor, alguien que me ayude. Quiero tomar una captura de pantalla de la función componible y compartirla con otras aplicaciones.
Ejemplo de mi función:
@Composable fun PhotoCard() { Stack() { Image(imageResource(id = R.drawable.background)) Text(text = "Example") } }¿Cómo tomar una captura de pantalla de esta función?
Usar PixelCopy funcionó para mí:
@RequiresApi(Build.VERSION_CODES.O) suspend fun Window.drawToBitmap( config: Bitmap.Config = Bitmap.Config.ARGB_8888, timeoutInMs: Long = 1000 ): Bitmap { var result = PixelCopy.ERROR_UNKNOWN val latch = CountDownLatch(1) val bitmap = Bitmap.createBitmap(decorView.width, decorView.height, config) PixelCopy.request(this, bitmap, { copyResult -> result = copyResult latch.countDown() }, Handler(Looper.getMainLooper())) var timeout = false withContext(Dispatchers.IO) { runCatching { timeout = !latch.await(timeoutInMs, TimeUnit.MILLISECONDS) } } if (timeout) error("Failed waiting for PixelCopy") if (result != PixelCopy.SUCCESS) error("Non success result: $result") return bitmap }Ejemplo:
val scope = rememberCoroutineScope() val context = LocalContext.current as Activity var bitmap by remember { mutableStateOf<Bitmap?>(null) } Button(onClick = { scope.launch { //wrap in a try catch/block if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { bitmap = context.window.drawToBitmap() } } }) { Text(text = "Take Screenshot") } Box( modifier = Modifier .background(Color.Red) .padding(10.dp) ) { bitmap?.let { Image( bitmap = it.asImageBitmap(), contentDescription = null, modifier = Modifier.fillMaxSize(), ) } }Puede obtener la posición de una vista componible dentro de la vista de composición raíz usando onGloballyPositioned y luego dibujar la parte necesaria de la vista raíz en el Bitmap de bits:
val view = LocalView.current var capturingViewBounds by remember { mutableStateOf<Rect?>(null) } Button(onClick = { val bounds = capturingViewBounds ?: return@Button val image = Bitmap.createBitmap( bounds.width.roundToInt(), bounds.height.roundToInt(), Bitmap.Config.ARGB_8888 ).applyCanvas { translate(-bounds.left, -bounds.top) view.draw(this) } }) { Text("Capture") } ViewToCapture( modifier = Modifier .onGloballyPositioned { capturingViewBounds = it.boundsInRoot() } ) Tenga en cuenta que si tiene alguna vista en la parte superior de ViewToCapture , como colocada con un Box , seguirá estando en la imagen.
ps, hay un error que hace que los efectos Modifier.graphicsLayer , offset { IntOffset(...) } (todavía puede usar offset(dp) en este caso), la posición de vistas perezosas y scrollable no se muestre correctamente en la captura de pantalla. Si lo ha enfrentado, marque el problema para obtener más atención.
Como @Commonsware mencionó en el comentario, y suponiendo que no se trata de pruebas de captura de pantalla:
De acuerdo con los documentos oficiales , puede acceder a la versión de vista de su función componible usando LocalView.current y exportar esa vista a un archivo de mapa de bits como este (el siguiente código va dentro de la función componible):
val view = LocalView.current val context = LocalContext.current val handler = Handler(Looper.getMainLooper()) handler.postDelayed(Runnable { val bmp = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888).applyCanvas { view.draw(this) } bmp.let { File(context.filesDir, "screenshot.png") .writeBitmap(bmp, Bitmap.CompressFormat.PNG, 85) } }, 1000) El método writeBitmap es una función de extensión simple para la clase File. Ejemplo:
private fun File.writeBitmap(bitmap: Bitmap, format: Bitmap.CompressFormat, quality: Int) { outputStream().use { out -> bitmap.compress(format, quality, out) out.flush() } }Estaba buscando cómo tomar una captura de pantalla de un componible en las pruebas y esta pregunta apareció como la primera en los resultados. Entonces, para los futuros usuarios que quieran tomar/guardar/comparar capturas de pantalla en pruebas o hacer pruebas de capturas de pantalla , pongo mi respuesta aquí (gracias a esto ).
Asegúrate de tener esta dependencia junto con otras dependencias de Compose:
debugImplementation("androidx.compose.ui:ui-test-manifest:<version>") Nota: En lugar de la dependencia anterior, simplemente puede agregar un archivo AndroidManifest.xml en el directorio androidTest y agregar <activity android:name="androidx.activity.ComponentActivity" /> en el manifest ➜ elemento de application .
Consulte esta respuesta .
El siguiente es un ejemplo completo de tomar, guardar, leer y comparar capturas de pantalla de una función componible llamada MyComposableFunction :
class ScreenshotTest { @get:Rule val composeTestRule = createComposeRule() @Test fun takeAndSaveScreenshot() { composeTestRule.setContent { MyComposableFunction() } val node = composeTestRule.onRoot() val screenshot = node.captureToImage().asAndroidBitmap() saveScreenshot("screenshot.png", screenshot) } @Test fun readAndCompareScreenshots() { composeTestRule.setContent { MyComposableFunction() } val node = composeTestRule.onRoot() val screenshot = node.captureToImage().asAndroidBitmap() val context = InstrumentationRegistry.getInstrumentation().targetContext val path = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) val file = File(path, "screenshot.png") val saved = readScreenshot(file) println("Are screenshots the same: ${screenshot.sameAs(saved)}") } private fun readScreenshot(file: File) = BitmapFactory.decodeFile(file.path) private fun saveScreenshot(filename: String, screenshot: Bitmap) { val context = InstrumentationRegistry.getInstrumentation().targetContext // Saves in /Android/data/your.package.name.test/files/Pictures on external storage val path = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) val file = File(path, filename) file.outputStream().use { stream -> screenshot.compress(Bitmap.CompressFormat.PNG, 100, stream) } } }También he respondido una pregunta similar aquí .
Puede crear una prueba, establecer el contenido en ese componible y luego llamar a composeTestRule.captureToImage() . Devuelve un ImageBitmap .
Ejemplo de uso en un comparador de capturas de pantalla: https://github.com/android/compose-samples/blob/e6994123804b976083fa937d3f5bf926da4facc5/Rally/app/src/androidTest/java/com/example/compose/rally/ScreenshotComparator.kt
Puede crear una función de vista previa con @Preview, ejecutar la función en el teléfono o emulador y tomar la captura de pantalla del componente.