Android & Kotlin

How to create Shimmer Effect in Jetpack Compose

Pinterest LinkedIn Tumblr

In this blog, I will show how to implement the shimmer effect in an Android app using Jetpack Compose. This tutorial shares exactly how to get it done quickly shimmer loading effect with Jetpack Compose.

Add the Shimmer Animation Components

Before creating the shimmer effect, you’ll need to set up your Jetpack Compose environment. Make sure you have a project open in Android Studio and that you’ve imported the necessary dependencies needed for Jetpack Compose (e.g., androidx.compose).

Once you done with dependency let create a @Composable function named with ShimmerItem.

@Composable
fun ShimmerItem(
  isLoading: Boolean, actualContent: @Composable () -> Unit, modifier: Modifier = Modifier
) {
  // If actual content is in loading state , display it shimmer Items
  if (isLoading) {
    Row(modifier = modifier) {
      Box(
        modifier = Modifier
          .fillMaxWidth()
           
      )
    }
  } else {
    // If actual content is loaded, display it
    actualContent()
  }
}

Customize the Shimmer View.

At the above snapshot I just created one box, Now we have to customised it based on view. So below code snippet, I creating a shimmer view as per feature image, You can create as per own actual view.

@Composable
fun ShimmerItem(
  isLoading: Boolean, actualContent: @Composable () -> Unit, modifier: Modifier = Modifier
) {
  // If actual content is in loading state , display it shimmer Items
  if (isLoading) {
    Row(modifier = modifier) {
      Box(
        modifier = Modifier
          .size(80.dp)
          .clip(CircleShape)
          .shimmerEffect()
      )
      Spacer(modifier = Modifier.width(16.dp))
      Column(
        modifier = Modifier
          .weight(1f)
          .align(CenterVertically)
      ) {
        Box(
          modifier = Modifier
            .fillMaxWidth()
            .height(20.dp)
            .shimmerEffect()
        )
        Spacer(modifier = Modifier.height(16.dp))
        Box(
          modifier = Modifier
            .fillMaxWidth(0.7f)
            .height(20.dp)
            .shimmerEffect()
        )
      }
    }
  } else {
    // If actual content is loaded, display it
    actualContent()
  }
}

Set the Colors, Angle and Opacity for the Shine in the Shimmer Effect.

It time to add shimmer effect on View that we created. So let create a Kotlin extension like Modifier.shimmerEffect and set the color, animation angle and the opacity of View.

private fun Modifier.shimmerEffect(): Modifier = composed {
  var size by remember {
    mutableStateOf(IntSize.Zero)
  }
  val transition = rememberInfiniteTransition()
  val startOffsetX by transition.animateFloat(
    initialValue = -2 * size.width.toFloat(),
    targetValue = 2 * size.width.toFloat(),
    animationSpec = infiniteRepeatable(
      animation = tween(1000)
    )
  )

  background(
    brush = Brush.linearGradient(
      colors = listOf(
        Color(0xFFB9B5B5),
        Color(0xFF837F7F),
        Color(0xFFC2C1C1),
      ),
      start = Offset(startOffsetX, 0f),
      end = Offset(startOffsetX + size.width.toFloat(), size.height.toFloat())
    )
  ).onGloballyPositioned {
    size = it.size
  }
}

Complete source shimmer loading effect Item View

package com.compose.shimmereffectexample

import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp

@Composable
fun ShimmerItem(
  isLoading: Boolean, actualContent: @Composable () -> Unit, modifier: Modifier = Modifier
) {
  // If actual content is in loading state , display it shimmer Items
  if (isLoading) {
    Row(modifier = modifier) {
      Box(
        modifier = Modifier
          .size(80.dp)
          .clip(CircleShape)
          .shimmerEffect()
      )
      Spacer(modifier = Modifier.width(16.dp))
      Column(
        modifier = Modifier
          .weight(1f)
          .align(CenterVertically)
      ) {
        Box(
          modifier = Modifier
            .fillMaxWidth()
            .height(20.dp)
            .shimmerEffect()
        )
        Spacer(modifier = Modifier.height(16.dp))
        Box(
          modifier = Modifier
            .fillMaxWidth(0.7f)
            .height(20.dp)
            .shimmerEffect()
        )
      }
    }
  } else {
    // If actual content is loaded, display it
    actualContent()
  }
}

private fun Modifier.shimmerEffect(): Modifier = composed {
  var size by remember {
    mutableStateOf(IntSize.Zero)
  }
  val transition = rememberInfiniteTransition()
  val startOffsetX by transition.animateFloat(
    initialValue = -2 * size.width.toFloat(),
    targetValue = 2 * size.width.toFloat(),
    animationSpec = infiniteRepeatable(
      animation = tween(1000)
    )
  )

  background(
    brush = Brush.linearGradient(
      colors = listOf(
        Color(0xFFB9B5B5),
        Color(0xFF837F7F),
        Color(0xFFC2C1C1),
      ),
      start = Offset(startOffsetX, 0f),
      end = Offset(startOffsetX + size.width.toFloat(), size.height.toFloat())
    )
  ).onGloballyPositioned {
    size = it.size
  }
}

How to use Shimmer Effect with own View

In this shimmer effect android example, will show shimmer loading effect until actual content is loading. Just like attached video. If you wish to show how to create list follow out this Ultimate Guide to Jetpack Compose List. Let create composable list in actual content and use ShimmerItem on that. just like below

package com.compose.shimmereffectexample

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.compose.shimmereffectexample.ui.theme.ShimmerEffectExampleTheme
import kotlinx.coroutines.delay

class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      ShimmerEffectExampleTheme {
        var isLoading by remember {
          mutableStateOf(true)
        }
        LaunchedEffect(key1 = true) {
          delay(2000)
          isLoading = false
        }
        // Call Shimmer effect using Jetpack Compose
        ShimmerEffectListView(isLoading)
      }
    }
  }
}

@Composable
fun ShimmerEffectListView(isLoading: Boolean) {
  LazyColumn(
    modifier = Modifier.fillMaxSize()
  ) {
    items(20) {
      ShimmerItem(
        isLoading = isLoading,
        actualContent = { ActualContent() },
        modifier = Modifier
          .fillMaxWidth()
          .padding(16.dp)
      )
    }
  }
}

/**
 * Actual Listview that you want to display once shimmer goes out
 */
@Composable
fun ActualContent() {
  Row(
    modifier = Modifier
      .fillMaxWidth()
      .padding(16.dp)
  ) {
    Icon(
      imageVector = Icons.Default.AccountCircle,
      contentDescription = null,
      modifier = Modifier.size(80.dp)
    )
    Spacer(modifier = Modifier.width(16.dp))
    Text(
      text = "This is a  text to show that our shimmer loading effect " + "is looking good",
      modifier = Modifier.align(CenterVertically)
    )
  }
}

Conclusion

So far what we done in tutorial, We create on ShimmerItem that with color and animation, Same Item view we have used in List. Let run the project, it will run and up, so that way you can create a Shimmer Effect in an Android using Jetpack Compose.

If you have any query please let me know. Follow me on social media for latest articles

Download Source code

Write A Comment