Animating brush Text coloring in Compose 🖌️
After adding a gradient to your text in Compose, now it’s time to animate it!
This post builds up on text styling using the
Brush API and Compose animations! Make sure you’re familiar with these concepts. We covered all the integrations using the
Brush API on this blog post here.
Candy cane shimmer effect
We want to implement a candy cane effect for the gradient in our text. The colors in the gradient should move from the top left to the bottom right corner of the text continuously, as per our design:
We can use
linearGradient to create the gradient, which places the colors along given
Because of how linear gradient works, the coordinates define the area and angle at which the linear brush paints. For our example, if you define a region as described by the image below, the brush stroke is diagonally cropped, which is easy to see if the brush size is smaller than the drawing area:
So an idea to implement this animation is to animate
end coordinates in a small section of the drawing area and then repeat the sequence.
We can define an infinite transition, and use
animateFloat to animate a value from 0f to at least twice your font size in pixels. Because we don’t know the drawing area size in this case, we are using font size as an anchor point, which directly relates to the area of the drawn text.
We can use this animated offset next, make the gradient move in a specific area of the canvas, and then repeat this sequence in the rest of the available space. This is how the first step would look like without repetition:
We can create the linear gradient brush, configure the
end coordinates of the drawing area using the animated offset, and apply it to the text. We start in the (0,0) coordinate and then move up until our defined offset.
To repeat the sequence and create the effect of continuity, we can use
mirror. So the code looks like this:
That’s it! You’ve achieved the candy cane effect that works for any text size and density of your device.
You can create other types of effects (for example a faster transition or a thicker gradient) by tweaking offset’s
targetValueand the gradient’s
Back and forth shimmer effect
Next, we have a new animation, consisting of a gradient rocking back and forth.
In the previous example we used the
currentFontSizePx to estimate how big the area of the animation would be, and using an estimate was good enough to achieve the effect we wanted. But sometimes, we may want to know the exact size occupied by the text or drawing area. To access this size (which is also the brush size), we can create a custom brush, as we did in the Custom brushes section, in the previous post.
We can start thinking how to draw the first pass of the gradient’s movement, with coordinates that are a function of an animated
offset and the width and height of the drawing area.
Let’s define an infinite transition, animating a range from 0f to 1f. We can configure
RepeatMode.Reverse, so the gradient can be painted moving in one direction and then in the opposite direction.
Because of the gradient pattern, we can create a linear gradient brush using the
LinearGradientShader method. Same as before, from and to represent the coordinates where the brush will paint.
We can define
heightOffset variables, that scale the width and height based on the animated offset.
And then we can use
mirror to fill the drawing space with the inverse gradient allowing the effect of moving back and forth.
Finally, we set the new brush to
Text. The code might look something like this:
We are using the
remember function to allow recomposition whenever
offset changes. This is necessary because, due to an internal optimization in
AndroidTextPaint, if the brush or its direct parameters are not changing no recomposition will be scheduled. In this case, brush remains the same, and what changes is the
And you’re done, you’ve achieved the design above ✨.
You’ve learned how to use the animation APIs with the different
Brush APIs and some techniques to make your gradient colors come to life.
Give it a try in your app and let us know if you experience any issues by filing a bug on our issue tracker.
Happy Composing! 👋