![]() |
VOOZH | about |
Jetpack Compose is a new UI toolkit from Google used to create native Android UI. It speeds up and simplifies UI development using less code, Kotlin APIs, and powerful tools.
Prerequisites:
A sample video is given below to get an idea about what we will do in this article.
Step 1: Create a new Android studio project
To create a new project in Android Studio using Jetpack Compose please refer to:- How to Create a New Project in Android Studio Canary Version with Jetpack Compose.
Step 2: Let’s first review the build.gradle(module level)
Now go to the module-level build.gradle file & check on dependencies. If any of the dependencies are missing add them from the below snippet. Remember to double-check this file that everything is included. If something is missing just add those blocks from the below snippets.
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
plugins {
alias(libs.plugins.com.android.application)
alias(libs.plugins.org.jetbrains.kotlin.android)
}
android {
namespace = "com.example.jetpackthemepicker"
compileSdk = 33
defaultConfig {
applicationId = "com.example.jetpackthemepicker"
minSdk = 24
targetSdk = 33
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.3.2"
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
dependencies {
constraints {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.10") {
because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib")
}
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10") {
because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib")
}
}
implementation(libs.core.ktx)
implementation(libs.lifecycle.runtime.ktx)
implementation(libs.activity.compose)
implementation(platform(libs.compose.bom))
implementation(libs.ui)
implementation(libs.ui.graphics)
implementation(libs.ui.tooling.preview)
implementation(libs.material3)
implementation("androidx.core:core-ktx:1.10.0")
implementation("com.google.android.material:material:1.8.0")
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core)
androidTestImplementation(platform(libs.compose.bom))
androidTestImplementation(libs.ui.test.junit4)
debugImplementation(libs.ui.tooling)
debugImplementation(libs.ui.test.manifest)
}
Step 3: Now let's review the build.gradle(project level)
Remember to double-check this file that everything is included. If something is missing just add those blocks from the below snippets.
// Top-level build file where you can add configuration
// options common to all sub-projects/modules.
plugins {
alias(libs.plugins.com.android.application) apply false
alias(libs.plugins.org.jetbrains.kotlin.android) apply false
}
Step 4: Now let's review the libs.versions.toml(Version Catalog) and settings.gradle.kts
These files are special files that were introduced in the latest update of the Android version i.e. Android Studio Giraffe | 2022.3.1 Canary 11. A description of what this file holds onto is given below :
libs.versions.toml
[versions]
com-android-application = "8.1.0-alpha11"
org-jetbrains-kotlin-android = "1.7.20"
core-ktx = "1.9.0"
junit = "4.13.2"
androidx-test-ext-junit = "1.1.5"
espresso-core = "3.5.1"
lifecycle-runtime-ktx = "2.3.1"
activity-compose = "1.5.1"
compose-bom = "2022.10.00"
[libraries]
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" }
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" }
lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle-runtime-ktx" }
activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity-compose" }
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
ui = { group = "androidx.compose.ui", name = "ui" }
ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
material3 = { group = "androidx.compose.material3", name = "material3" }
[plugins]
com-android-application = { id = "com.android.application", version.ref = "com-android-application" }
org-jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version = "1.7.20" }
[bundles]
settings.gradle.kts
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "JetpackThemePicker"
include(":app")
Step 5: Adding more colors to colors.xml and adding themes.xml
Add some colors for the theme picker and use them in different customization of themes. Goto Android->res->values->colors.xml and add the following stub of code:
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimaryDark">#EB495C</color> <color name="colorPrimary">#E16876</color> <color name="colorPrimaryVariant">#E4A8AF</color> <color name="purple_200">#FFBB86FC</color> <color name="purple_500">#FF6200EE</color> <color name="purple_700">#FF3700B3</color> <color name="teal_200">#FF03DAC5</color> <color name="teal_700">#FF018786</color> <color name="black">#FF000000</color> <color name="white">#FFFFFFFF</color> <color name="blue">#0984e3</color> <color name="fruit">#6c5ce7</color> <color name="pink">#EF5366</color> <color name="orange">#e17055</color> <color name="pink40">#64EF5366</color> <color name="pink50">#80EF5366</color> </resources>
Now goto Android->res->values->themes.xml and add the following stub of code:
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/tools"> <style name="Theme.JetpackThemePicker" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <!-- Primary brand color. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryVariant">@color/colorPrimaryDark</item> <item name="colorOnPrimary">@color/white</item> <!-- Secondary brand color. --> <item name="colorSecondary">@color/teal_200</item> <item name="colorSecondaryVariant">@color/teal_700</item> <item name="colorOnSecondary">@color/black</item> <!-- Status bar color. --> <item name="android:statusBarColor" >?attr/colorPrimaryVariant</item> <!-- Customize your theme here. --> </style> <style name="Theme.JetpackThemePicker.NoActionBar"> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> </style> <style name="Theme.JetpackThemePicker.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> <style name="Theme.JetpackThemePicker.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> </resources>
Step 6: Now let's define the UI flow and navigation flow for the screens
This is the MainActivity class, which extends ComponentActivity.
Step 7: Creating a model data class of the Component
Create a new package as a model and create a Kotlin dataclass file in it named Component. This Component data class will have two properties: componentName and className.
Step 8: Create a class that can be used as a state variable for managing the theme of the app (AppThemeState)
Goto Android -> Java -> com -> example -> ui -> theme and create a data class file named as AppThemeState. This class will have two properties:
The data keyword used before the class definition automatically generates some methods such as equals(), hashCode(), toString(), and copy() for the class based on the properties defined in it.
This class can be used as a state variable for managing the theme of the app in a Jetpack Compose UI. When the darkTheme or palette properties of this class change, the UI that is using this state variable will recompose itself with the new values.
Step 9: Define colors, shapes, and typography for the theme
We will define some colors, shapes, and typography for the theme palette to choose from. You can also tinker with the values according to your preferences. Goto Android=>app=>java=>com=>example=>packagename(Here jetpackthemepicker)=>ui=>Color.kt and paste this stub of code
Color.kt
Goto Android=>app=>java=>com=>example=>packagename(Here jetpackthemepicker)=>ui=>Shape.kt and paste this stub of code
Shape.kt
Goto Android=>app=>java=>com=>example=>packagename(Here jetpackthemepicker)=>ui=>Type.kt and paste this stub of code
Type.kt
Step 10: Let us create a class named "SystemUI.kt" that provides methods to change the color of the status and navigation bars
This is a SystemUiController class that provides methods to change the color of the status and navigation bars on an Android device. The SystemUiController class takes a Window object as its constructor parameter, which is used to set the status and navigation bar colors. The class has three methods:
We also define a LocalSystemUiController object, which can be used as a Composable function to provide the SystemUiController to the composition. Additionally, we define two private Color values and a lambda that can be used to transform the color for light content.
Step 11: For a custom Compose theme let's declare several predefined color palettes for light and dark modes in themes.kt
Let's create a custom Compose theme with several predefined color palettes for light and dark modes. In this class, we will declare 10 predefined color palettes for both light and dark modes. The colors are defined using the Color class provided by Compose, and the palettes are created using the darkColorScheme() and lightColorScheme() functions.
The ColorPalette enum class is used to specify which color palette to use. The JetpackTheme() function is the main entry point of the theme and takes in two parameters: darkTheme and colorPalette. The darkTheme parameter specifies whether to use the dark or light mode of the theme based on the system's current mode. The colorPalette parameter specifies which color palette to use for the theme.
The content parameter is a composable function that represents the content of the screen or component that the theme is applied to. To apply this theme to a Composable function or a screen, you need to wrap the content with the JetpackTheme() function and pass the desired darkTheme and colorPalette parameters.
Step 12: Now let's define a new Activity class ThemeActivity which lets the users change the theme of the screen
Step 13: Now let's register this new ThemeActivity as an activity in AndroidManifest.xml