Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Text Gradient in Android Jetpack Compose

Can't figure out how to add a gradient to a text with an inner shadow with a modifier in Jetpack Compose. To have something like this? Any ideas?

enter image description here

like image 285
Dmytro Filipenko Avatar asked Oct 05 '20 06:10

Dmytro Filipenko


3 Answers

Just ran into the same use case, but just for a simple gradient on text. Posting it here in case it helps someone.

What worked for me was drawing the content and then the gradient via Modifier.graphicsLayer (extrapolated from this answer on Slack):

Text(
   text = "$ 20",
   /** size/font style, etc. **/
   modifier = Modifier.graphicsLayer(alpha = 0.99f)
     .drawWithCache {
        val brush = Brush.horizontalGradient(listOf(StartColor, EndColor))
        onDrawWithContent {
            drawContent()
            drawRect(brush, blendMode = BlendMode.SrcAtop)
        }
     }
)

I ended up making it a Modifier for reuse:

fun Modifier.textBrush(brush: Brush) = this
   .graphicsLayer(alpha = 0.99f)
   .drawWithCache {
      onDrawWithContent {
         drawContent()
         drawRect(brush, blendMode = BlendMode.SrcAtop)
      }
   }

Example Result:

text with gradient

like image 172
nebulasmoothie Avatar answered Oct 19 '22 14:10

nebulasmoothie


So far jetpack compose doesn't provide text gradient and inner shadow out of the box. Hence need to paint it by yourself:

result image

@Composable
fun drawGradientText(name: String, modifier: Modifier = Modifier) {

    val paint = Paint().asFrameworkPaint()

    val gradientShader: Shader = LinearGradientShader(
        from = Offset(0f, 0f),
        to = Offset(0f, 400f),
        listOf(Color.Blue, Color.Cyan)
    )

    Canvas(modifier.fillMaxSize()) {
        paint.apply {
            isAntiAlias = true
            textSize = 400f
            typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
            style = android.graphics.Paint.Style.FILL
            color = android.graphics.Color.parseColor("#cdcdcd")
            xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER)
            maskFilter = BlurMaskFilter(30f, Blur.NORMAL)
        }
        drawIntoCanvas { canvas ->
            canvas.save()
            canvas.nativeCanvas.translate(2f, 5f)
            canvas.nativeCanvas.drawText(name, 0f, 400f, paint)
            canvas.restore()
            paint.shader = gradientShader
            paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
            paint.maskFilter = null
            canvas.nativeCanvas.drawText(name, 0f, 400f, paint)
            canvas.nativeCanvas.translate(2f, 5f)
            paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER)
            paint.maskFilter = BlurMaskFilter(30f, Blur.NORMAL)
            canvas.nativeCanvas.drawText(name, 0f, 400f, paint)
        }
        paint.reset()
    }
}

You can adjust PorterDuff modes and offsets to meet your requirements.

like image 26
VasiliyT Avatar answered Oct 19 '22 14:10

VasiliyT


In Jetpack Compose 1.2.0-beta01 text gradients were added.

Example:

@Composable
fun BrushDemo() {
    Text(
        "Brush is awesome\nBrush is awesome\nBrush is awesome",
        style = TextStyle(
            brush = Brush.linearGradient(
                colors = RainbowColors,
                tileMode = TileMode.Mirror
            ),
            fontSize = 30.sp
        )
    )
}

More examples here.

like image 8
Anton Popov Avatar answered Oct 19 '22 12:10

Anton Popov