Design Your Own Shimmering UI in 25 Lines of Code with Composeโ€‚by@leonidivankin

Design Your Own Shimmering UI in 25 Lines of Code with Compose

Read on Terminal Reader
Open TLDR
react to story with heart
react to story with light
react to story with boat
react to story with money
The full algorithm for adding compose to a project can be found here: eYou can copy the full code of the ShimmeringActivity. The color can be changed to white, as it should be in your project. The width, height, cornerRadius and radius of the circle, as in any other compose view, is necessary to make the animation for all elements work synchronously. The value of translateAnim will change over time.
image
Leonid Ivankin HackerNoon profile picture

Leonid Ivankin

I'm a developer


Shimmering is present in almost all applications that have networking. When the task of making it on compose came up, given that the latter simplifies the work with the view, I did not find a solution. All options were reduced to downloading fairly heavy libraries or writing a lot of code. However, I managed to find a solution, which allows me to make a shimmering on compose in a few lines of code.

Observations and Assumptions

  • my solution won't cover 100% of the cases of shimmering, but it's easy to refine;
  • my solution will be built around the Brush.linearGradient() method. There are probably more options, but this one seemed the easiest to me;
  • Don't forget to include compose if it's a new project, like buildFeatures {compose true}, composeOptions and others. The full algorithm for adding compose to a project can be found here: https://developer.android.com/jetpack/compose/setup.

Description

I am first attaching the full code of the ShimmeringActivity. You can copy it into your project and run it:

As a result, you should have the following animation:


image


Don't be intimidated by the orange and blue shimmering colors. I did this on purpose so that they would be easily distinguishable. The color can be changed to white, as it should be in your project.


Let's go through the code. Let's start with an easy one:

ShimmeringCompose(
   modifier = Modifier
       .width(300.dp)
       .height(150.dp),
   cornerRadius = 16.dp
)

width, height, cornerRadius - the width, height and radius of the circle, as in any other compose view.


image

val screenWidth = LocalConfiguration.current.screenWidthDp.dp

screenWidth - the found screen width. This is necessary to make the animation for all elements work synchronously. Otherwise, if there are several rectangles with different widths on the same screen, the shimmering for them will be out of sync, because the animation will run different distances at the same time.


val translateAnim by rememberInfiniteTransition().animateFloat(
   initialValue = 0f,
   targetValue = screenWidth.px,
   animationSpec = infiniteRepeatable(
       animation = tween(durationMillis = 1500, easing = FastOutSlowInEasing)
   )
)

rememberInfiniteTransition().animateFloat(), infiniteRepeatable() - methods for creating infinite animation.


initialValue, targetValue - start and end value of the animation.

tween() - method for configuring the animation.

durationMillis - animation time.

easing - interpolation of the animation.

The value of translateAnim will change over time from initialValue to targetValue. The translateAnim change logs:


D: ShimmeringCompose: 1.2176096
D: ShimmeringCompose: 2.7215502
D: ShimmeringCompose: 7.4594655
D: ShimmeringCompose: 11.377052
D: ShimmeringCompose: 21.533459
D: ShimmeringCompose: 27.730642
D: ShimmeringCompose: 34.646053
D: ShimmeringCompose: 53.458187
D: ShimmeringCompose: 64.20549
D: ShimmeringCompose: 91.909676
D: ShimmeringCompose: 107.303856


val shimmerColorShades = listOf(Color(0xFFF37F19), Color(0xFF007CFF), Color(0xFFF37F19))


With this list the colors are set: blue in the center and orange on the edges.

image

val brush = Brush.linearGradient(
   colors = shimmerColorShades,
   start = Offset(translateAnim, translateAnim),
   end = Offset(translateAnim + 70.dp.px, translateAnim + 35.dp.px)
)

Brush.linearGradient() is a method for creating a gradient.

In colors we assign the sheet of colors created above.

Offset() is a shell class for assigning x and y coordinates

The values 70 and 35 are chosen depending on the shimmering design in Figma.

image

Box(modifier = modifier.background(brush = brush, shape = RoundedCornerShape(cornerRadius)))

Create a Box object and assign to it in background() the values of brush and RoundedCornerShape to create rounded corners.


You will also need a utility method to translate dp to px:

val Dp.px: Float
    @Composable
    get() = with(LocalDensity.current) { [email protected]() }

As a result, we get animation, as in the gif-picture at the beginning of the article.

A few words about Brush.linearGradient()

To understand how Brush.linearGradient() works, change the code in the ShimmeringActivity to the following:

val brush = Brush.linearGradient(
   colors = shimmerColorShades,
   start = Offset(0f, 0f),
   end = Offset(0f, 100f)
)

You will end up with the following picture:

image

If you set x_start = x_end, the shimmer bar will be parallel to the x-axis. The thickness will be y_end - y_start, in this case 100f. Now insert the following code:

val brush = Brush.linearGradient(
   colors = shimmerColorShades,
   start = Offset(0f, 0f),
   end = Offset(100f, 0f)
)

You will get this picture:

image

If you set the y_start = y_end coordinates, the shimmer bar will be parallel to the y-axis. The thickness will be x_end - x_start, in this case 100f.

Thus, by manipulating the start and end coordinates, you can achieve the desired result.

Conclusion

As you can see, creating shimmering took about 25 lines of code, not including the ShimmeringActivity code and the utility method for translating to px. From my point of view, pulling in an additional library to create the shimmering makes no sense. Yes, my example isn't exactly clean from a code point of view: some variables aren't moved here and critical situations aren't handled. But it can be easily modified to the needs of your project.

react to story with heart
react to story with light
react to story with boat
react to story with money
L O A D I N G
. . . comments & more!