Background Color Transition Animation in Android Jetpack Compose
Many Android applications include an offer page or discount tags that change colors continuously to capture the attention of users. The principle underlying such bars/tags/coupons color shifting UI is the background color transition effect. In this post, we will look at how to create such background color transition effects.
Prerequisites:
- Familiar with Kotlin and OOP Concepts as well
- Basic understanding of Jetpack Compose
- Android Studio Canary Version
An example clip is provided below to demonstrate how the background color transition effect appears.
Step-by-Step Implementation
Step 1: Create a New Project in Android Studio
To create a new project in Android Studio please refer to How to Create a New Project in Android Studio Canary Version with Jetpack Compose. While choosing the template, select Empty Compose Activity. If you do not find this template, try upgrading the Android Studio to the latest version. We demonstrated the application in Kotlin, so make sure you select Kotlin as the primary language while creating a New Project.
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.
plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' } android { namespace 'com.example.colortransition' compileSdk 33 defaultConfig { applicationId "com.example.colortransition" minSdk 21 targetSdk 33 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary true } } buildTypes { release { minifyEnabled 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 compose_version } packagingOptions { resources { excludes += '/META-INF/{AL2.0,LGPL2.1}' } } } dependencies { implementation 'androidx.core:core-ktx:1.9.0' implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' implementation 'androidx.activity:activity-compose:1.6.1' implementation 'androidx.appcompat:appcompat:1.5.1' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.4' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0-RC" implementation'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' }
Step 3: Now let’s review the build.gradle(project level)
Now go to the project-level build.gradle file & check on buildscript code block. If any of the requirements are missing then add them from the below snippet.
buildscript { ext { kotlin_version = '1.0.1-2' compose_version = '1.1.0-rc01' } //Requirements repositories { google() mavenCentral() } dependencies { //dependency classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" } }// Top-level build file where you can add configuration options // common to all sub-projects/modules. plugins { id 'com.android.application' version '7.3.0-alpha01' apply false id 'com.android.library' version '7.3.0-alpha01' apply false id 'org.jetbrains.kotlin.android' version '1.6.0' apply false }
Step 4: Now rename MainActivity.kt to Animation2Activity.kt
We can put the same code to MainActivity.kt as well, but it’s a good idea to create or rename the file to reflect its role. Once you change this we also need to modify the AndroidManifest.xml activity tag to the renamed file since the default is MainActivity. You can refer to the below snippet of AndroidManifest.xml.
XML
<? xml version = "1.0" encoding = "utf-8" ?> < manifest xmlns:android = "http://schemas.android.com/apk/res/android" xmlns:tools = "http://schemas.android.com/tools" > < application android:allowBackup = "true" android:dataExtractionRules = "@xml/data_extraction_rules" android:fullBackupContent = "@xml/backup_rules" android:icon = "@mipmap/ic_launcher" android:label = "@string/app_name" android:roundIcon = "@mipmap/ic_launcher_round" android:supportsRtl = "true" android:theme = "@style/Theme.ColorTransition" tools:targetApi = "31" > < activity android:name = ".Animation2Activity" android:exported = "true" android:label = "@string/app_name" android:theme = "@style/Theme.AppCompat" > < intent-filter > < action android:name = "android.intent.action.MAIN" /> < category android:name = "android.intent.category.LAUNCHER" /> </ intent-filter > </ activity > </ application > </ manifest > |
Step 5: Implement AppCompatActivity() to class Animation2Activity
SetContent() block will set the AnimateColorComponent component function as the root view of the activity. The AnimateColorComponent() will have the logic for the background color transition effect.
Kotlin
import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import androidx.compose.animation.Animatable import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview class Animation2Activity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super .onCreate(savedInstanceState) // This sets the @Composable function as the root view of the activity. // This is meant to replace the .xml file that we would typically // set using the setContent(R.id.xml_file) method. setContent { AnimateColorComponent() } } } |
Step 6: Create a composable function for making the background color transition possible
Before we go, there are a few things you should be aware of:
- Composable annotations: The @Composable annotation is used to indicate a Composable function. Composable functions can only be invoked from other composable functions. Consider composable functions to be comparable to Lego blocks in that each composable function is constructed up of smaller composable functions.
- Animatable: It’s a value holder prop that animates the value we obtain from the animateTo property.
- LaunchedEffect: The LaunchedEffect creates a new scope for a specific time interval until [given key value] it varies off.
- Column: The column is composable and places its children in a vertical sequence. It is comparable to a LinearLayout in that it is vertically oriented. Additionally, we add a modifier to the column.
- Modifier: Modifiers serve as examples of the decorator pattern and are used to alter the composable to which they are applied. In this case, we use the Modifier to set the Column up to take up the whole available width and height using the Modifier.fillMaxSize() modifier.
Kotlin
@Composable fun AnimateColorComponent() { // Animatable is a value holder that can animate // the value as it is changed via animateTo val color = remember { Animatable(Color.Red) } // using the LaunchedEffect composable to create a scope // just for the duration of the specified key value. LaunchedEffect(Unit) { color.animateTo(Color.Red, animationSpec = tween( 1500 )) color.animateTo(Color.Gray, animationSpec = tween( 1500 )) color.animateTo(Color.Blue, animationSpec = tween( 1500 )) color.animateTo(Color.Black, animationSpec = tween( 1500 )) color.animateTo(Color.Yellow, animationSpec = tween( 1500 )) color.animateTo(Color.Cyan, animationSpec = tween( 1500 )) } // Below, we use color to get get the latest value of color and use it to // paint the screen by setting it as the backgroundColor of the screen. Column(modifier = Modifier.fillMaxSize().background(color.value)) { } } |
Step 7: If you want to preview your AnimateColorComponent then continue else you can skip it
Significance of @preview and composable annotations :
- Instead of needing to download the app to an Android device or emulator, Android Studio allows you to preview your composable functions within the IDE itself. This is an excellent feature since it allows you to preview every one of your components—or composable functions—right inside the IDE
- The composable function cannot accept any parameters, which is the fundamental constraint. You may just include your component within another composable function that doesn’t take any arguments and calls your composable function with the necessary parameters
- Also, don’t forget to annotate it with @Preview & @Composable annotations
// Significance of @Preview & @Composable annotations @Preview @Composable fun AnimateColorComponentPreview() { AnimateColorComponent() }
Step 8: Complete the code snippet
Kotlin
import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import androidx.compose.animation.Animatable import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview class Animation2Activity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super .onCreate(savedInstanceState) // This sets the @Composable function as the root view of the activity. // This is meant to replace the .xml file that we would typically // set using the setContent(R.id.xml_file) method. setContent { AnimateColorComponent() } } } @Composable fun AnimateColorComponent() { // Animatable is a value holder that can animate // the value as it is changed via animateTo val color = remember { Animatable(Color.Red) } // using the LaunchedEffect composable to create a scope // just for the duration of the specified key value. LaunchedEffect(Unit) { color.animateTo(Color.Red, animationSpec = tween( 1500 )) color.animateTo(Color.Gray, animationSpec = tween( 1500 )) color.animateTo(Color.Blue, animationSpec = tween( 1500 )) color.animateTo(Color.Black, animationSpec = tween( 1500 )) color.animateTo(Color.Yellow, animationSpec = tween( 1500 )) color.animateTo(Color.Cyan, animationSpec = tween( 1500 )) } // Below, we use color to get get the latest value of color and use it to // paint the screen by setting it as the backgroundColor of the screen. Column(modifier = Modifier.fillMaxSize().background(color.value)) { } } // Significance of @Preview & @Composable annotations @Preview @Composable fun AnimateColorComponentPreview() { AnimateColorComponent() } |
Output:
As we can see with the help of jetpack compose the background color transition animation was developed.
Contact Us