Skip to content

Commit 987bf47

Browse files
Merge pull request #513 from JoseAlcerreca/composepreview
Adds Compose Preview Screenshot sample
2 parents a59d128 + 72bf339 commit 987bf47

36 files changed

+1317
-0
lines changed

.github/ci-gradle.properties

Whitespace-only changes.
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Workflow name
2+
name: Compose Preview Screenshot
3+
on:
4+
# When it will be triggered
5+
# And in which branch
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v3
14+
15+
- name: Set Up JDK
16+
uses: actions/setup-java@v3
17+
with:
18+
distribution: 'zulu' # See 'Supported distributions' for available options
19+
java-version: '17'
20+
cache: 'gradle'
21+
22+
- name: Build project and run screenshot tests
23+
working-directory: ./ui/PreviewScreenshot
24+
run: ./gradlew validateDebugScreenshotTest

ui/PreviewScreenshot/.gitignore

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
*.iml
2+
.gradle
3+
/local.properties
4+
/.idea/caches
5+
/.idea/libraries
6+
/.idea/modules.xml
7+
/.idea/workspace.xml
8+
/.idea/navEditor.xml
9+
/.idea/assetWizardSettings.xml
10+
.DS_Store
11+
/build
12+
/captures
13+
.externalNativeBuild
14+
.cxx
15+
local.properties

ui/PreviewScreenshot/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Compose Preview Screenshot Testing tool
2+
3+
Experimental: Compose Preview Screenshot Testing is still in development. Its
4+
features and APIs are subject to change substantially during the alpha phase.
5+
Report any feedback and issues through the [issue tracker](https://d.android.com/studio/report-bugs).
6+
7+
See [Compose Preview Screenshot Testing](https://d.android.com/studio/preview/compose-screenshot-testing).

ui/PreviewScreenshot/app/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build
+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright (C) 2024 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
plugins {
18+
alias(libs.plugins.android.application)
19+
alias(libs.plugins.jetbrains.kotlin.android)
20+
alias(libs.plugins.screenshot)
21+
}
22+
23+
android {
24+
namespace = "com.example.compose.previewscreenshot"
25+
compileSdk = 34
26+
27+
defaultConfig {
28+
applicationId = "com.example.compose.previewscreenshot"
29+
minSdk = 24
30+
targetSdk = 34
31+
versionCode = 1
32+
versionName = "1.0"
33+
34+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
35+
vectorDrawables {
36+
useSupportLibrary = true
37+
}
38+
}
39+
40+
buildTypes {
41+
release {
42+
isMinifyEnabled = false
43+
proguardFiles(
44+
getDefaultProguardFile("proguard-android-optimize.txt"),
45+
"proguard-rules.pro"
46+
)
47+
}
48+
}
49+
compileOptions {
50+
sourceCompatibility = JavaVersion.VERSION_1_8
51+
targetCompatibility = JavaVersion.VERSION_1_8
52+
}
53+
kotlinOptions {
54+
jvmTarget = "1.8"
55+
}
56+
buildFeatures {
57+
compose = true
58+
}
59+
composeOptions {
60+
kotlinCompilerExtensionVersion = "1.5.13"
61+
}
62+
63+
experimentalProperties["android.experimental.enableScreenshotTest"] = true
64+
65+
packaging {
66+
resources {
67+
excludes += "/META-INF/{AL2.0,LGPL2.1}"
68+
}
69+
}
70+
}
71+
72+
dependencies {
73+
74+
implementation(libs.androidx.core.ktx)
75+
implementation(libs.androidx.lifecycle.runtime.ktx)
76+
implementation(libs.androidx.activity.compose)
77+
implementation(platform(libs.androidx.compose.bom))
78+
implementation(libs.androidx.ui)
79+
implementation(libs.androidx.ui.graphics)
80+
implementation(libs.androidx.ui.tooling.preview)
81+
implementation(libs.androidx.material3)
82+
testImplementation(libs.junit)
83+
androidTestImplementation(libs.androidx.junit)
84+
androidTestImplementation(libs.androidx.espresso.core)
85+
androidTestImplementation(platform(libs.androidx.compose.bom))
86+
androidTestImplementation(libs.androidx.ui.test.junit4)
87+
debugImplementation(libs.androidx.ui.tooling)
88+
debugImplementation(libs.androidx.ui.test.manifest)
89+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ Copyright (C) 2024 The Android Open Source Project
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ http://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
18+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
19+
xmlns:tools="http://schemas.android.com/tools">
20+
21+
<application
22+
android:allowBackup="false"
23+
android:dataExtractionRules="@xml/data_extraction_rules"
24+
android:fullBackupContent="@xml/backup_rules"
25+
android:icon="@mipmap/ic_launcher"
26+
android:label="@string/app_name"
27+
android:roundIcon="@mipmap/ic_launcher_round"
28+
android:supportsRtl="true"
29+
android:theme="@style/Theme.ComposePreviewScreenshotTestingSample"
30+
tools:targetApi="31">
31+
<activity
32+
android:name=".MainActivity"
33+
android:exported="true"
34+
android:label="@string/app_name"
35+
android:theme="@style/Theme.ComposePreviewScreenshotTestingSample">
36+
<intent-filter>
37+
<action android:name="android.intent.action.MAIN" />
38+
39+
<category android:name="android.intent.category.LAUNCHER" />
40+
</intent-filter>
41+
</activity>
42+
</application>
43+
44+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (C) 2024 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.compose.previewscreenshot
18+
19+
import android.content.res.Configuration
20+
import android.os.Bundle
21+
import androidx.activity.ComponentActivity
22+
import androidx.activity.compose.setContent
23+
import androidx.activity.enableEdgeToEdge
24+
import androidx.compose.foundation.layout.fillMaxSize
25+
import androidx.compose.foundation.layout.padding
26+
import androidx.compose.material3.Scaffold
27+
import androidx.compose.material3.Surface
28+
import androidx.compose.material3.Text
29+
import androidx.compose.runtime.Composable
30+
import androidx.compose.ui.Modifier
31+
import androidx.compose.ui.res.stringResource
32+
import androidx.compose.ui.tooling.preview.Preview
33+
import com.example.compose.previewscreenshot.ui.theme.SampleTheme
34+
35+
class MainActivity : ComponentActivity() {
36+
override fun onCreate(savedInstanceState: Bundle?) {
37+
super.onCreate(savedInstanceState)
38+
enableEdgeToEdge()
39+
setContent {
40+
SampleTheme {
41+
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
42+
Greeting(
43+
modifier = Modifier.padding(innerPadding)
44+
)
45+
}
46+
}
47+
}
48+
}
49+
}
50+
51+
@Composable
52+
fun Greeting(modifier: Modifier = Modifier) {
53+
Surface {
54+
Text(
55+
text = stringResource(id = R.string.greeting),
56+
modifier = modifier
57+
)
58+
}
59+
}
60+
61+
@Preview(showBackground = true)
62+
@Preview(showBackground = true, locale = "es")
63+
@Preview(showBackground = true, name = "Dark" , uiMode = Configuration.UI_MODE_NIGHT_YES)
64+
@Composable
65+
fun GreetingPreview() {
66+
SampleTheme {
67+
Greeting()
68+
}
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (C) 2024 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.compose.previewscreenshot.ui.theme
18+
19+
import androidx.compose.ui.graphics.Color
20+
21+
val Purple80 = Color(0xFFD0BCFF)
22+
val PurpleGrey80 = Color(0xFFCCC2DC)
23+
val Pink80 = Color(0xFFEFB8C8)
24+
25+
val Purple40 = Color(0xFF6650a4)
26+
val PurpleGrey40 = Color(0xFF625b71)
27+
val Pink40 = Color(0xFF7D5260)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (C) 2024 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.compose.previewscreenshot.ui.theme
18+
19+
import android.os.Build
20+
import androidx.compose.foundation.isSystemInDarkTheme
21+
import androidx.compose.material3.MaterialTheme
22+
import androidx.compose.material3.darkColorScheme
23+
import androidx.compose.material3.dynamicDarkColorScheme
24+
import androidx.compose.material3.dynamicLightColorScheme
25+
import androidx.compose.material3.lightColorScheme
26+
import androidx.compose.runtime.Composable
27+
import androidx.compose.ui.platform.LocalContext
28+
29+
private val DarkColorScheme = darkColorScheme(
30+
primary = Purple80,
31+
secondary = PurpleGrey80,
32+
tertiary = Pink80
33+
)
34+
35+
private val LightColorScheme = lightColorScheme(
36+
primary = Purple40,
37+
secondary = PurpleGrey40,
38+
tertiary = Pink40
39+
40+
/* Other default colors to override
41+
background = Color(0xFFFFFBFE),
42+
surface = Color(0xFFFFFBFE),
43+
onPrimary = Color.White,
44+
onSecondary = Color.White,
45+
onTertiary = Color.White,
46+
onBackground = Color(0xFF1C1B1F),
47+
onSurface = Color(0xFF1C1B1F),
48+
*/
49+
)
50+
51+
@Composable
52+
fun SampleTheme(
53+
darkTheme: Boolean = isSystemInDarkTheme(),
54+
// Dynamic color is available on Android 12+
55+
dynamicColor: Boolean = true,
56+
content: @Composable () -> Unit
57+
) {
58+
val colorScheme = when {
59+
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
60+
val context = LocalContext.current
61+
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
62+
}
63+
64+
darkTheme -> DarkColorScheme
65+
else -> LightColorScheme
66+
}
67+
68+
MaterialTheme(
69+
colorScheme = colorScheme,
70+
typography = Typography,
71+
content = content
72+
)
73+
}

0 commit comments

Comments
 (0)