Open In App

Motion Layout Button in Android Jetpack Compose

Last Updated : 29 Sep, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Motion Layout is a special version of Constraint layout. With the help of motion layout, we can add animations to the widgets within the layout and change the position of that widget dynamically. In this article, we will take a look at How to implement Motion Layout animation on buttons in Android using Jetpack compose

What we are going to build in this article? 

We will be building a simple application in which we will be displaying two image buttons. These buttons are aligned vertically by default. On clicking on any of the buttons the buttons will animate and are arranged in a horizontal manner. 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 Project in Android Studio

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. 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: Adding dependency in build.gradle

Navigate to Gradle Scripts > build.gradle file and add the below dependency in the dependencies section. 

implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-rc01"

After adding this dependency sync this project to install the dependency. 

Step 3: Adding new colors in the Color.kt file

Navigate to the app > java > your app’s package name > ui.theme > Color.kt file and add the below code to it. 

Kotlin




package com.example.newcanaryproject.ui.theme
 
import androidx.compose.ui.graphics.Color
 
val Purple200 = Color(0xFF0F9D58)
val Purple500 = Color(0xFF0F9D58)
val Purple700 = Color(0xFF3700B3)
val Teal200 = Color(0xFF03DAC5)
 
// on below line we are
// adding different colors
val greenColor = Color(0xFF0F9D58)


Step 4: Working with the MainActivity.kt file

Go to the MainActivity.kt file and refer to the following code. Below is the code for the MainActivity.kt file. Comments are added inside the code to understand the code in more detail.

Kotlin




package com.example.newcanaryproject
 
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Typeface
import android.os.Bundle
 
import android.speech.RecognizerIntent
import android.speech.SpeechRecognizer
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.annotation.Dimension.DP
import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Mic
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.*
import androidx.compose.ui.viewinterop.AndroidView
import androidx.constraintlayout.compose.ConstraintSet
import androidx.constraintlayout.compose.MotionLayout
import com.example.newcanaryproject.ui.theme.*
import com.github.mikephil.charting.charts.PieChart
import com.github.mikephil.charting.components.Description
import com.github.mikephil.charting.components.Legend
import com.github.mikephil.charting.data.PieData
import com.github.mikephil.charting.data.PieDataSet
import com.github.mikephil.charting.data.PieEntry
import org.intellij.lang.annotations.JdkConstants.HorizontalAlignment
import java.util.*
 
class MainActivity : ComponentActivity() {
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NewCanaryProjectTheme {
                // on below line we are specifying
                // background color for our application
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    // on below line we are specifying theme as scaffold.
                    Scaffold(
                        // in scaffold we are specifying top bar.
                        topBar = {
                            // inside top bar we are specifying background color.
                            TopAppBar(backgroundColor = greenColor,
                                // along with that we are specifying title for our top bar.
                                title = {
                                    // in the top bar we are specifying tile as a text
                                    Text(
                                        // on below line we are specifying
                                        // text to display in top app bar.
                                        text = "MotionLayout Button",
                                         
                                        // on below line we are specifying modifier
                                        // to fill max width.
                                        modifier = Modifier.fillMaxWidth(),
                                         
                                        // on below line we are
                                        // specifying text alignment.
                                        textAlign = TextAlign.Center,
                                         
                                        // on below line we are specifying
                                        // color for our text.
                                        color = Color.White
                                    )
                                }
                            )
                        }
                    ) {
                        // on below line we are creating a box
                        Box(
                            // in this box we are specifying a modifier
                            // and specifying a max size
                            modifier = Modifier
                                .fillMaxSize(),
                            
                            // on below line we are specifying center alignment
                            contentAlignment = Alignment.Center,
                        ) {
                            // on below line we are calling
                            // motion layout button method.
                            MotionLayoutButton()
                        }
                    }
                }
            }
        }
    }
}
 
// on below line we are creating
// a motion layout button method.
@OptIn(ExperimentalUnitApi::class)
@Composable
fun MotionLayoutButton() {
    // on below line we are specifying animate button method.
    var animateButton by remember { mutableStateOf(false) }
    // on below line we are specifying button animation progress
    val buttonAnimationProgress by animateFloatAsState(
        
        // specifying target value on below line.
        targetValue = if (animateButton) 1f else 0f,
         
        // on below line we are specifying
        // animation specific duration's 1 sec
        animationSpec = tween(1000)
    )
 
    // on below line we are creating a motion layout.
    MotionLayout(
        // in motion layout we are specifying 2 constraint
        // set for two different positions of buttons.
        // in first constraint set we are specifying width,
        // height start, end and top position of buttons.
        ConstraintSet(
            """ {
                // on below line we are specifying width,height and margin
                // from start, top and end for button1
                button1: {
                  width: "spread",
                  height: 120,
                  start: ['parent', 'start', 16],
                  end: ['parent', 'end', 16],
                  top: ['parent', 'top', 0]
                },
                // on below line we are specifying width,height
                // and margin from start, top and end for button2
                button2: {
                  width: "spread",
                  height: 120,
                  start: ['parent', 'start', 16],
                  end: ['parent', 'end', 16],
                  top: ['button1', 'bottom', 16]
                }
            } """
        ),
 
        // in second constraint set we are specifying width,
        // height start, end and top position of buttons.
        ConstraintSet(
            """ {
                // on below line we are specifying width,height and margin
                // from start, top and end for button1
                button1: {
                  width: 150,
                  height: 120,
                  start: ['parent', 'start', 30],
                  end: ['button2', 'start', 10]
                },
                // on below line we are specifying width,height
                // and margin from start, top and end for button2
                button2: {
                  width: 150,
                  height: 120,
                  start: ['button1', 'end', 10],
                  end: ['parent', 'end', 30]
                }
            } """
        ),
        // on below line we are specifying
        // progress for button animation
        progress = buttonAnimationProgress,
        // on below line we are specifying modifier
        // for filling max width and content height.
        modifier = Modifier
            .fillMaxWidth()
            .wrapContentHeight()
    ) {
        // on below line we are creating  a button.
        Button(
            // on below line we are adding on click.
            onClick = {
                // inside on click we are animating button
                // by simply changing animateButton variable
                animateButton = !animateButton
            },
            // on below line we are
            // specifying id for our button 1
            modifier = Modifier.layoutId("button1")
        ) {
            // on below line we are adding content
            // inside our button in the form of column.
            Column(
                // in this column we are specifying a
                // modifier with padding from all sides.
                modifier = Modifier
                    .padding(3.dp)
                    .fillMaxWidth()
                    .fillMaxHeight(),
                // on below line we are specifying vertical
                // and horizontal arrangement for our column
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                // on the below line we are specifying an image inside our column
                Image(
                     
                    // on below line we are specifying
                    // the drawable image for our image.
                    painter = painterResource(id = R.drawable.python),
                     
                    // on below line we are specifying
                    // content description for our image
                    contentDescription = "Python",
                     
                    // on below line we are setting
                    // height and width for our image.
                    modifier = Modifier
                        .height(60.dp)
                        .width(60.dp)
                )
                // on below line we are adding spacer/
                Spacer(modifier = Modifier.height(5.dp))
                 
                // below spacer we are adding a
                // simple text for displaying a text
                Text(
                    text = "Python",
                    color = Color.White,
                    fontSize = TextUnit(value = 18F, type = TextUnitType.Sp)
                )
            }
        }
 
        // on the below line we are creating a button.
        Button(
            onClick = {
                // inside on click we are animating button
                // by simply changing animateButton variable
                animateButton = !animateButton
            },
            // on below line we are specifying id for our button 2
            modifier = Modifier.layoutId("button2")
        ) {
            Column(
                // in this column we are specifying
                // a modifier with padding from all sides.
                modifier = Modifier
                    .padding(3.dp)
                    .fillMaxWidth()
                    .fillMaxHeight(),
                // on below line we are specifying vertical
                // and horizontal arrangement for our column
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                // on below line we are specifying image inside our column
                Image(
                    // on below line we are specifying
                    // the drawable image for our image.
                    painter = painterResource(id = R.drawable.js),
                     
                    // on below line we are specifying
                    // content description for our image
                    contentDescription = "Javascript",
                     
                    // on below line we are setting
                    // height and width for our image.
                    modifier = Modifier
                        .height(60.dp)
                        .width(60.dp)
                )
                // on below line we are adding spacer/
                Spacer(modifier = Modifier.height(5.dp))
                 
                // below spacer we are adding a
                // simple text for displaying a text
                Text(
                    text = "JavaScript",
                    color = Color.White,
                    fontSize = TextUnit(value = 18F, type = TextUnitType.Sp)
                )
 
            }
        }
    }
}


Now run your application to see the output of it.

Output:



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads