Open In App
Related Articles

Background Color Transition Animation in Android Jetpack Compose

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Report issue
Report

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:

  1. Familiar with Kotlin and OOP Concepts as well
  2. Basic understanding of Jetpack Compose
  3. 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"?>
    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.



Last Updated : 24 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads