[译]使用 Jetpack Compose 自动生成精美的应用截图

screen-shot

截图是用户对我们应用的第一印象。因此,为了展现最好的一面,我们需要展示精心设计的截图。但是图形化设计截图是一项耗时的工作。在想出独特的设计后,你还需要将其应用到应用的所有变体中。这可能包括手机或平板电脑、多种语言本地化等。而且当你更新界面时,你还需要重新进行这个过程,至少要重新处理受影响的截图。自动化截图能够解决大部分这些问题。像 fastlane 这样的工具使我们能够自动获取应用在所有不同变体中的截图,所需时间仅为人工操作的一小部分。但这样做的缺点是自动化截图会失去有助于在竞争中脱颖而出的独特性。在本文中,我们将使用 UI 测试和 Jetpack Compose 来设计我们的截图,并使用 fastlane 自动捕获它们。

开始之前

编排截图

获取简单截图

class MyComposeTest {  
  
	@get:Rule  
	val composeTestRule = createAndroidComposeRule<TestActivity>()  
  
    @Rule  
	 @JvmField val localeTestRule = LocaleTestRule()  
  
    @Before  
	fun init() {  
		Screengrab
			.setDefaultScreenshotStrategy(
				UiAutomatorScreenshotStrategy()
			)  
    }  
  
    @Test  
	fun simpleScreenshot() {  
        composeTestRule.setContent {  
            ScreenshotsTheme {  
                App()  
            }  
        }  
        composeTestRule.takeScreenshot("simpleScreenshot")  
    }
}

shot-img02

这是如何获取简单截图的方法。在测试本身之前,我们有一些用于设置 fastlane 截图工具的代码。但最重要的部分是在 composeTestRule.setContent 内。在这里,我们可以使用设计普通应用时可用的任何可组合项。例如,我们可以为整个应用添加一些内边距和阴影。

composeTestRule.setContent {  
    ScreenshotsTheme {  
        Box(  
            modifier = Modifier  
				.fillMaxSize()  
                .padding(30.dp)  
                .shadow(
	                elevation = 18.dp, 
	                shape = RoundedCornerShape(10.dp))  
                .clip(RoundedCornerShape(10.dp))  
        ) {  
            App()  
        }  
    }  
}

添加标题和背景

// 从这里开始,你只受限于你的想象力(或你的设计师的想象力 ;)。你可以添加解释截图的标题,添加背景,突出显示某个功能等。

composeTestRule.setContent {  
    ScreenshotsTheme {  
        Box(  
            Modifier  
				.fillMaxSize()  
                .background(Color.White)  
        ) {  
  
            Box(  
                modifier = Modifier  
					.align(Alignment.TopEnd)  
                    .offset(x = 10.dp, y = 30.dp)  
                    .size(200.dp)  
                    .background(
	                    color = MaterialTheme.colors.secondary,
	                    shape = CircleShape
                    )  
            )  
            Box(  
                modifier = Modifier  
					.align(Alignment.TopStart)  
                    .offset(x = 40.dp, y = 130.dp)  
                    .size(50.dp)  
                    .background(
	                    color = MaterialTheme.colors.primary,
	                    shape = CircleShape
                    )
            )  
            Column(  
                modifier = Modifier  
					.verticalScroll(
						state = rememberScrollState(),
						reverseScrolling = false)  
                    .fillMaxSize()  
            ) {  
  
                Text(  
                    text = "Tasks app",  
                    textAlign = TextAlign.Center,  
                    fontSize = 48.sp,  
                    fontWeight = FontWeight.Black,  
                    modifier = Modifier  
						.fillMaxWidth()  
                        .padding(vertical = 94.dp)  
                )  
  
                Box(  
                    modifier = Modifier  
						.fillMaxWidth()  
                        .height(640.dp)  
                        .padding(horizontal = 30.dp)  
                        .shadow(
	                        elevation = 18.dp, 
	                        shape = RoundedCornerShape(10.dp))  
                        .clip(RoundedCornerShape(10.dp))  
                ) {  
                    App()  
                }  
            }  
        }  
    }  
}

shot-img03

浅色和暗色模式

在这个例子中,我在应用上方添加了一些文本并向下偏移。我还使用两个盒子添加了一个简单的背景。你也可以实例化应用的两个版本来显示应用的多个版本。

Row(...) {  
    Box(  
        ...
    ) {  
        ScreenshotsTheme(darkTheme = false) {  
            App()  
        }  
  
    }  
  
    Box(  
        ...
    ) {  
        ScreenshotsTheme(darkTheme = true) {  
            App()  
        }  
  
    }  
}

shot-img03

这里我们有应用的深色和浅色版本并排显示。因为 App 只是一个可组合项,我们可以轻松地并排创建两个版本。这在单个截图中显示应用的不同状态时很有用。

Fastlane

对于这个示例,我使用 fastlane 来自动运行 UI 测试并获取和管理截图。如果你的应用已本地化,它可以用多种语言获取截图,并自动上传到 Play Store。对于这个示例,我只有一个简单的 lane 来进行清理构建和获取截图。

lane :screenshots do  
  gradle(task: "clean assembleDebug assembleAndroidTest")  
  screengrab  
end

我还有一个文件,用于定义 apk 的位置以及我想要获取截图的语言。

locales ['en-US', 'de-DE']  
clear_previous_screenshots true  
tests_apk_path 'app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk'  
app_apk_path 'app/build/outputs/apk/debug/app-debug.apk'  
test_instrumentation_runner 'androidx.test.runner.AndroidJUnitRunner'

所以我也可以用相同的代码自动生成德语截图。

screen-shot_de

如何设置自动化取决于你和你的工作流程。但本文的主要目的是演示 Jetpack Compose 如何使我们在设计截图时具有灵活性。我希望通过这篇文章,你能够创建出令人惊叹的截图。示例项目的源代码在这里