How to Apply Stroke Effects to Text in Jetpack Compose

Exploring DrawStyle API for Text Stroke Effects in Jetpack Compose
Mar 22 2023 · 4 min read

Background

Jetpack Compose recently added lots of new customization options to TextStyle, TextStyle.drawStyle is one of them. Using this, we can apply stunning stroke effects to text in Jetpack Compose.

In this blog post, we’ll explore how to use DrawStyle API to create unique and creative stroke effects for texts.

So, if you’re ready to take your Jetpack Compose text designs to the next level, let’s dive in and explore DrawStyle API!

We are what we repeatedly do. Excellence, then, is not an act, but a habit. Try out Justly and start building your habits today!

Getting started

We’ll use Stroke drawStyle, which provides information for drawing content with a stroke.

Let’s first look at what we have in Stroke API,

class Stroke(
   val width: Float = 0.0f,
   val miter: Float = DefaultMiter,
   val cap: StrokeCap = DefaultCap,
   val join: StrokeJoin = DefaultJoin,
   val pathEffect: PathEffect? = null
) : DrawStyle() { }
  • width — Configure the width of the stroke in pixels
  • miter — Set the stroke miter value. This is used to control the behavior of miter joins when the joins angle is sharp. This value must be >= 0
  • cap — Return the paint’s Cap, controlling how the start and end of stroked lines and paths are treated. The default is StrokeCap.Butt
  • join — Set the treatment where lines and curve segments join on a stroked path. The default is StrokeJoin.Miter
  • pathEffect — Effect to apply to the stroke, null indicates a solid stroke line is to be drawn

Now Let’s implement cool Stroke Effects.

Draw Simple outlined text

 Text(
            text = "Applying Cool Stroke Effects to Text",
            style = LocalTextStyle.current.merge(
                TextStyle(color = Color(0xFFF67C37),
                    fontSize = 80.sp,
                    drawStyle = Stroke(width = 6f, join = StrokeJoin.Round)
                )
            )
        ) 

We just simply apply a stroke with a 6-pixel width and join to StrokeJoin.Round

Draw round-corner outlined text

Let’s chase the pathEffects to implement different effects.. We’ll use cornerPathEffect to round the sharp angle by radius. Here’s how,

Text(
    text = "Applying Cool Stroke Effects to Text",
    style = LocalTextStyle.current.merge(
        TextStyle(
            color = Color(0xFFF67C37),
            fontSize = 80.sp,
            drawStyle = Stroke(
                width = 6f, join = StrokeJoin.Round,
                pathEffect = PathEffect.cornerPathEffect(
                   radius = 40f
                )
            )
        )
    )
)

Draw dash stroke

For dash stroke we have dashPathEffect , which has intervals and phase params

  • intervals — Array of “on” and “off” distances for the dashed line segments
  • phase — Pixel offset into the intervals array
Text(
   text = "Applying Cool Stroke Effects to Text",
   style = LocalTextStyle.current.merge(
       TextStyle(
           color = Color(0xFFF67C37),
           fontSize = 80.sp,
           drawStyle = Stroke(
               width = 6f, join = StrokeJoin.Round,
               pathEffect = PathEffect.dashPathEffect(
                   intervals = floatArrayOf(20f, 10f),
                   phase = 0f
               )
           )
       )
   )
)

Here’s the result

Draw the outline with multiple path effects

We can also apply multiple effects to outline paths using chainPathEffect Let’s apply the dashed effect with the corner path.

@Composable
fun MultiplePathEffectDemo() {
   val dashPathEffect = remember {
       PathEffect.dashPathEffect(
           intervals = floatArrayOf(20f, 10f),
           0f
       )
   }
   val cornerPathEffect = remember {
       PathEffect.cornerPathEffect(
           80f
       )
   }
   Text(
       text = "Applying Cool Stroke Effects to Text",
       style = LocalTextStyle.current.merge(
           TextStyle(
               color = Color(0xFFF67C37),
               fontSize = 80.sp,
               drawStyle = Stroke(
                   width = 6f, join = StrokeJoin.Round,
                   pathEffect = PathEffect.chainPathEffect(dashPathEffect, cornerPathEffect)
               )
           )
       )
   )
}

Draw double outlines

val customPath = remember {
    val p = Path()
    p.moveTo(-15f, 6f)
    p.lineTo(15f, 6f)
    p.lineTo(15f, 2f)
    p.lineTo(-15f, 2f)
    p.close()
    p.moveTo(-15f, -6f)
    p.lineTo(15f, -6f)
    p.lineTo(15f, -2f)
    p.lineTo(-15f, -2f)
    p
}

val stampEffect = remember {
    PathEffect.stampedPathEffect(
        customPath, 40f, 0f, StampedPathEffectStyle.Morph
    )
}
Text(
    text = "Applying Cool Stroke Effects to Text",
    style = LocalTextStyle.current.merge(
        TextStyle(
            color = Color(0xFFF67C37),
            fontSize = 80.sp,
            drawStyle = Stroke(
                width = 6f, join = StrokeJoin.Round,
                pathEffect = stampEffect
            )
        )
    )
)

Draw Gradient outline

Here we’ll use Brush API to add gradient stroke.

@Composable
fun GradientOutlineDemo() {
   Text(
       text = "Applying Cool Stroke Effects to Text",
       style = LocalTextStyle.current.merge(
           TextStyle(
               fontSize = 80.sp,
               brush = Brush.horizontalGradient(
                   listOf(
                       Color.Blue,
                       Color.Magenta,
                       Color.Red,
                       Color.Yellow
                   )
               ),
               drawStyle = Stroke(
                   width = 6f, join = StrokeJoin.Round,
                   pathEffect = PathEffect.cornerPathEffect(
                       80f
                   )
               )
           )
       )
   )
}


 

Draw outline with shapes

Let’s have some fun with stroke effects.

We can draw different shapes using a path and stamp them on an outline using stampedPathEffect.

Example 1 — Curved outline

We’ll draw half circle shape and stamp on to outline. Here’s how

@Composable
fun CustomOutlineDemo() {
   val customPath = Path().apply {
       moveTo(-10f, 0f)
       arcTo(
           Rect(-10f, -10f, 10f, 10f),
           180f,
           180f,
           false
       );
   }
   val stampEffect = remember {
       PathEffect.stampedPathEffect(
           customPath, 20f, 0f, StampedPathEffectStyle.Morph
       )
   }
   Text(
       text = "Jetpack compose",
       style = LocalTextStyle.current.merge(
           TextStyle(
               fontSize = 80.sp,
               brush = Brush.horizontalGradient(
                   listOf(
                       Color.Blue,
                       Color.Magenta,
                       Color.Red,
                       Color.Yellow
                   )
               ),
               drawStyle = Stroke(
                   width = 6f, join = StrokeJoin.Round,
                   pathEffect = stampEffect
               )
           )
       )
   )
}

Example 2 — Heart shaped outline

@Composable
fun HeartShapeOutlineDemo() {
   val heartPath = remember {
       Path().apply {
           val width = 20f
           val height = 20f
           moveTo(width / 2, height / 4)
           cubicTo(width / 4, 0f, 0f, height / 3, width / 4, height / 2)
           lineTo(width / 2, height * 3 / 4)
           lineTo(width * 3 / 4, height / 2)
           cubicTo(width, height / 3, width * 3 / 4, 0f, width / 2, height / 4)
       }
   }
   val stampEffect = remember {
       PathEffect.stampedPathEffect(
           heartPath, 20f, 10f, StampedPathEffectStyle.Translate
       )
   }
   
   Text(
       text = "Jetpack compose",
       style = LocalTextStyle.current.merge(
           TextStyle(
               fontSize = 80.sp,
               brush = Brush.horizontalGradient(
                   listOf(
                       Color.Magenta,
                       Color.Red,
                       Color.Yellow
                   )
               ),
               drawStyle = Stroke(
                   width = 10f,
                   pathEffect = stampEffect
               )
           )
       )
   )
}

Conclusion

In this blog post, we’ve explored the exciting world of DrawStyle API in Jetpack Compose and learned how to apply cool stroke effects to text.

We hope this post has inspired you to experiment with DrawStyle API in your own projects and create stunning text designs that will make your app stand out. Remember, the possibilities are endless when it comes to text styling in Jetpack Compose, and with the right tools and techniques, you can create designs that are both beautiful and functional.

Thank you for reading, and happy coding! 👋


Code, Build, Repeat.
Stay updated with the latest trends and tutorials in Android, iOS, and web development.
radhika-s image
Radhika saliya
Mobile App Developer | Sharing knowledge of Jetpack Compose & android development
radhika-s image
Radhika saliya
Mobile App Developer | Sharing knowledge of Jetpack Compose & android development
canopas-logo
We build products that customers can't help but love!
Get in touch

Whether you need...

  • *
    High-performing mobile apps
  • *
    Bulletproof cloud solutions
  • *
    Custom solutions for your business.
Bring us your toughest challenge and we'll show you the path to a sleek solution.
Talk To Our Experts
footer
Follow us on
2024 Canopas Software LLP. All rights reserved.