在 Jetpack Compose 中以编程方式截取可组合乐趣的屏幕截图
Take screenshot of a composable fun programmatically in Jetpack Compose
我想将 Jetpack Compose 发出的 UI 捕获为位图。在 XML 中,这样做是这样的:
基本上将视图作为输入参数,returns将其作为位图。
//take screenshot of the view added as an input argument
fun takeScreenShot(view: View) : Bitmap {
val bitmap = Bitmap.createBitmap(
view.width,
view.height,
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
view.draw(canvas)
return bitmap
}
在 Jetpack compose 中这相当于什么?
我会看看 JP-Compose 测试是如何做到这一点的。
一个好的起点可以是 android-compose-codelab,参见:
/**
* Simple on-device screenshot comparator that uses golden images present in
* `androidTest/assets`. It's used to showcase the [AnimationClockTestRule] used in
* [AnimatingCircleTests].
*
* Minimum SDK is O. Densities between devices must match.
*
* Screenshots are saved on device in `/data/data/{package}/files`.
*/
@RequiresApi(Build.VERSION_CODES.O)
fun assertScreenshotMatchesGolden(
goldenName: String,
node: SemanticsNodeInteraction
) {
val bitmap = node.captureToImage().asAndroidBitmap()
}
来自 ScreenshotComparator.kt. You can find captureToImage()
here in the AndroidHelpers.kt。
您还可以在这里找到 ImageBitmap.kt, where asAndroidBitmap() 仅确保 ImageBitmap 的底层“通用”版本实际上是 Android 上的 android.graphics.Bitmap
(这是为了使代码与平台无关,因此它也可以在 JVM/desktop 上 运行)
在测试.
中可以从可组合项截取屏幕截图
要在生产代码中截取屏幕截图,请参阅 and this issue。
首先,确保您的构建脚本中具有以下依赖项(以及其他必需的 Compose 依赖项):
debugImplementation("androidx.compose.ui:ui-test-manifest:<version>")
注意:除了上面的依赖,你可以简单地在androidTest中添加一个AndroidManifest.xml目录并在 manifest
>application
元素中添加以下内容:<activity android:name="androidx.activity.ComponentActivity" />
.
参考this answer.
这里是保存、读取和比较屏幕截图的完整示例:
(请参考this post设置写入权限等测试)
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)
}
}
}
感谢 Google this 的代码实验室。
我想将 Jetpack Compose 发出的 UI 捕获为位图。在 XML 中,这样做是这样的:
基本上将视图作为输入参数,returns将其作为位图。
//take screenshot of the view added as an input argument
fun takeScreenShot(view: View) : Bitmap {
val bitmap = Bitmap.createBitmap(
view.width,
view.height,
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
view.draw(canvas)
return bitmap
}
在 Jetpack compose 中这相当于什么?
我会看看 JP-Compose 测试是如何做到这一点的。
一个好的起点可以是 android-compose-codelab,参见:
/**
* Simple on-device screenshot comparator that uses golden images present in
* `androidTest/assets`. It's used to showcase the [AnimationClockTestRule] used in
* [AnimatingCircleTests].
*
* Minimum SDK is O. Densities between devices must match.
*
* Screenshots are saved on device in `/data/data/{package}/files`.
*/
@RequiresApi(Build.VERSION_CODES.O)
fun assertScreenshotMatchesGolden(
goldenName: String,
node: SemanticsNodeInteraction
) {
val bitmap = node.captureToImage().asAndroidBitmap()
}
来自 ScreenshotComparator.kt. You can find captureToImage()
here in the AndroidHelpers.kt。
您还可以在这里找到 ImageBitmap.kt, where asAndroidBitmap() 仅确保 ImageBitmap 的底层“通用”版本实际上是 Android 上的 android.graphics.Bitmap
(这是为了使代码与平台无关,因此它也可以在 JVM/desktop 上 运行)
在测试.
中可以从可组合项截取屏幕截图
要在生产代码中截取屏幕截图,请参阅
首先,确保您的构建脚本中具有以下依赖项(以及其他必需的 Compose 依赖项):
debugImplementation("androidx.compose.ui:ui-test-manifest:<version>")
注意:除了上面的依赖,你可以简单地在androidTest中添加一个AndroidManifest.xml目录并在 manifest
>application
元素中添加以下内容:<activity android:name="androidx.activity.ComponentActivity" />
.
参考this answer.
这里是保存、读取和比较屏幕截图的完整示例:
(请参考this post设置写入权限等测试)
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)
}
}
}
感谢 Google this 的代码实验室。