Open In App

Android Jetpack Compose – Rotation Animation

Last Updated : 25 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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:

  1. Familiar with Kotlin and OOP Concepts as well
  2. Basic understanding of Jetpack Compose
  3. Android Studio Canary Version

A sample video is given below to get an idea about what we are going to do in this article.

Step-by-Step Implementation

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)

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.rotationanimation'
    compileSdk 33

    defaultConfig {
        applicationId "com.example.rotationanimation"
        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)

Remember to double-check this file that everything is included. If something is missing just add those blocks from the below snippets.

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 Animation1Activity.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.RotationAnimation"
        tools:targetApi="31">
        <activity
            android:name=".Animation1Activity"
            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: Importing necessary modules

It’s good practice to import only the necessary modules rather than importing all the modules and using only a few. 

Kotlin




import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.core.*
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.rotate
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp


Step 6: Implement AppCompatActivity() to class  Animation1Activity

Kotlin




class Animation1Activity : 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 {
            RotatingSquareComponent()
        }
    }
}


Step 7: Create a composable function for making custom themes

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.

  • 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.
  • Canvas: We use the Canvas composable that gives you access to a canvas that you can draw into.
  • rotate: Adds a rotation (in degrees clockwise) to the current transform at the given pivot point.
  • To draw a rectangle we will be using drawRect().
  • Few more examples to try on your own:)
  • To draw round rectangle use drawRoundRect()
  • To draw a circle use drawCircle()
  • To draw an arc use drawArc()
  • To draw an Image or use an image as animation use drawImage()
  • To draw a line use drawLine()
  • To draw an oval use drawOval()
  • To draw points use drawPoints()

Kotlin




@Composable
fun RotatingSquareComponent() {
    // Column with clickable modifier
    // wraps the child composable
    // and enables it to react to a
    // click through the onClick callback similar to
    // the onClick listener that we are accustomed
    // to on Android.
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
        content = {
            // rememberInfiniteTransition is utilized for creating
            // infinite transition in child animations
            // Animations usually gets invoked automatically
            // once they enter in a composable.
            val infiniteTransition = rememberInfiniteTransition()
 
            // Create a value that is altered by the transition based on the
            // configuration. We use the animated float value the returns and
            // updates a float from the initial value to
            // target value and repeats it
            // (as its called on the infititeTransition).
            val rotation by infiniteTransition.animateFloat(
                initialValue = 0f,
                targetValue = 360f,
                animationSpec = infiniteRepeatable(
                    animation = tween<Float>(
                        durationMillis = 3000,
                        easing = FastOutLinearInEasing,
                    ),
                )
            )
 
            // In this example, we assign a size
            // of 250dp to the Canvas using
            // Modifier.preferredSize(250.dp).
            Canvas(modifier = Modifier.size(250.dp)) {
                // As the Transition is changing the interpolating the value
                // of the animated float "rotation", you get access to all
                // the values including the intermediate values as
                // its  being updated. The value of "rotation" goes from
                // 0 to 360 and transitions infinitely due to the
                // infiniteRepeatable animationSpec used above.
                rotate(rotation) {
                    drawRect(color = Color(50, 205, 50))
                }
            }
        })
}


Step 8: If you want to preview your RotatingSquareComponent 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 own 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

Kotlin




// Combined significance of
// Preview & Composable annotations
@Preview
@Composable
fun RotatingSquareComponentPreview() {
    RotatingSquareComponent()
}


Step 9: Complete code snippet

Kotlin




// Code for developing rotation animation in android jetpack compose
 
// Please replace the name of package with your project name
package com.example.rotationanimation
 
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.core.*
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.rotate
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
 
class Animation1Activity : 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 {
            RotatingSquareComponent()
        }
    }
}
 
@Composable
fun RotatingSquareComponent() {
    // Column with clickable modifier
    // wraps the child composable
    // and enables it to react to a
    // click through the onClick callback similar to
    // the onClick listener that we are accustomed
    // to on Android.
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
        content = {
            // rememberInfiniteTransition is utilized for creating
            // infinite transition in child animations
            // Animations usually gets invoked automatically
            // once they enter in a composable.
            val infiniteTransition = rememberInfiniteTransition()
 
            // Create a value that is altered by the transition based on the
            // configuration. We use the animated float value the returns and
            // updates a float from the initial value to
            // target value and repeats it
            // (as its called on the infititeTransition).
            val rotation by infiniteTransition.animateFloat(
                initialValue = 0f,
                targetValue = 360f,
                animationSpec = infiniteRepeatable(
                    animation = tween<Float>(
                        durationMillis = 3000,
                        easing = FastOutLinearInEasing,
                    ),
                )
            )
 
            // In this example, we assign a size
            // of 250dp to the Canvas using
            // Modifier.preferredSize(250.dp).
            Canvas(modifier = Modifier.size(250.dp)) {
                // As the Transition is changing the interpolating the value
                // of the animated float "rotation", you get access to all
                // the values including the intermediate values as
                // its  being updated. The value of "rotation" goes from
                // 0 to 360 and transitions infinitely due to the
                // infiniteRepeatable animationSpec used above.
                rotate(rotation) {
                    drawRect(color = Color(50, 205, 50))
                }
            }
        })
}
 
// Combined significance of
// Preview & Composable annotations
@Preview
@Composable
fun RotatingSquareComponentPreview() {
    RotatingSquareComponent()
}


If any difficulties are faced check your Gradle files as well android manifest. If the error persists you can refer to this zip file.

Output:

As we can see with the help of jetpack compose the rotation of a square animation was developed.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads