Prerequisites:
- Basic Knowledge of Kotlin
- Basic knowledge of Jetpack Compose
Shimmer Animation was created by Facebook to show the loading screen while images are fetched from the server. Now we see shimmer animation in lots of places. In this article, we will take a look at the implementation of shimmer animation using the all-new Jetpack Compose. A sample GIF 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 (Or use it in the existing Compose project)
To create a new project in the Android Studio Canary version, refer to the article How to Create a new Project in the Android Studio Canary Version with Jetpack Compose.
Step 2: Add Colors
Before moving to coding animation, add colors that shimmer animation will require. Open Colors.kt (Present in ui/theme/Colors.kt)
val ShimmerColorShades = listOf(
Color.LightGray.copy(0.9f),
Color.LightGray.copy(0.2f),
Color.LightGray.copy(0.9f)
)
It’s a list of background colors of compostable which is going to be animated, notice the color at index 1, this part will change its location, giving the shimmer effect.
Step 3: Working with the MainActivity.kt file
Create a composable function on which the animation will take place
@Composable fun ShimmerItem( brush: Brush
) { // Column composable containing spacer shaped like a rectangle,
// set the [background]'s [brush] with the brush receiving from [ShimmerAnimation]
// Composable which is the Animation you are gonna create.
Column(modifier = Modifier.padding( 16 .dp)) {
Spacer(
modifier = Modifier
.fillMaxWidth()
.size( 250 .dp)
.background(brush = brush)
)
Spacer(
modifier = Modifier
.fillMaxWidth()
.height( 30 .dp)
.padding(vertical = 8 .dp)
.background(brush = brush)
)
}
} |
Let’s create the animation. Create a new composable function.
@Composable fun ShimmerAnimation( ) { /*
Create InfiniteTransition
which holds child animation like [Transition]
animations start running as soon as they enter
the composition and do not stop unless they are removed
*/
val transition = rememberInfiniteTransition()
val translateAnim by transition.animateFloat(
/*
Specify animation positions,
initial Values 0F means it
starts from 0 position
*/
initialValue = 0f,
targetValue = 1000f,
animationSpec = infiniteRepeatable(
// Tween Animates between values over specified [durationMillis]
tween(durationMillis = 1200 , easing = FastOutSlowInEasing),
RepeatMode.Reverse
)
)
/*
Create a gradient using the list of colors
Use Linear Gradient for animating in any direction according to requirement
start=specifies the position to start with in cartesian like system Offset(10f,10f) means x(10,0) , y(0,10)
end = Animate the end position to give the shimmer effect using the transition created above
*/
val brush = Brush.linearGradient(
colors = ShimmerColorShades,
start = Offset(10f, 10f),
end = Offset(translateAnim, translateAnim)
)
ShimmerItem(brush = brush)
} |
Call the ShimmerItem which is going to animate, and pass the Brush object,
Step 4: Lay down the animated ShimmerItem onto the screen
In class MainActivity
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
setContent {
ShimmerAnimationTheme(darkTheme = false ) {
Surface(color = MaterialTheme.colors.background) {
/*
Lazy column as I am adding multiple items for display purpose
create you UI according to requirement
*/
LazyColumn {
/*
Lay down the Shimmer Animated item 5 time
[repeat] is like a loop which executes the body
according to the number specified
*/
repeat( 5 ) {
item {
ShimmerAnimation()
}
}
}
}
}
}
}
} |
And we are done. This is the final code for MainActivity.kt file.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.*
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.shimmeranimation.ui.theme.ShimmerAnimationTheme
import com.example.shimmeranimation.ui.theme.ShimmerColorShades
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
setContent {
ShimmerAnimationTheme(darkTheme = false ) {
Surface(color = MaterialTheme.colors.background) {
/*
Lazy column as I am adding multiple items for display purpose
create you UI according to requirement
*/
LazyColumn {
/**
Lay down the Shimmer Animated item 5 time
[repeat] is like a loop which executes the body
according to the number specified
*/
repeat( 5 ) {
item {
ShimmerAnimation()
}
}
}
}
}
}
}
} @Composable fun ShimmerAnimation( ) { /*
Create InfiniteTransition
which holds child animation like [Transition]
animations start running as soon as they enter
the composition and do not stop unless they are removed
*/
val transition = rememberInfiniteTransition()
val translateAnim by transition.animateFloat(
/*
Specify animation positions,
initial Values 0F means it starts from 0 position
*/
initialValue = 0f,
targetValue = 1000f,
animationSpec = infiniteRepeatable(
/*
Tween Animates between values over specified [durationMillis]
*/
tween(durationMillis = 1200 , easing = FastOutSlowInEasing),
RepeatMode.Reverse
)
)
/*
Create a gradient using the list of colors
Use Linear Gradient for animating in any direction according to requirement
start=specifies the position to start with in cartesian like system Offset(10f,10f) means x(10,0) , y(0,10)
end= Animate the end position to give the shimmer effect using the transition created above
*/
val brush = Brush.linearGradient(
colors = ShimmerColorShades,
start = Offset(10f, 10f),
end = Offset(translateAnim, translateAnim)
)
ShimmerItem(brush = brush)
} @Composable fun ShimmerItem( brush: Brush
) { /*
Column composable shaped like a rectangle,
set the [background]'s [brush] with the
brush receiving from [ShimmerAnimation]
which will get animated.
Add few more Composable to test
*/
Column(modifier = Modifier.padding( 16 .dp)) {
Spacer(
modifier = Modifier
.fillMaxWidth()
.size( 250 .dp)
.background(brush = brush)
)
Spacer(
modifier = Modifier
.fillMaxWidth()
.height( 30 .dp)
.padding(vertical = 8 .dp)
.background(brush = brush)
)
}
} |
Output:
Get the complete project.