DEV Community

Cover image for Using gradient for styling text
Chris Margonis
Chris Margonis

Posted on

3

Using gradient for styling text

Having an engaging and fancy user interface is essential for providing a delightful user experience. In some cases, this calls for using gradient colors. While Android’s styling system is pretty powerful, it lacks an out-of-the-box way to style a text using a gradient for coloring its text. Since at Plum we always try to explore new ways to achieve the best results, we had to come up with a solution!

CharacterStyle to the rescue!

Thankfully the android.text.style package contains enough tools for extending the already-provided styling capabilities. There’re many ways to extend it, but for this case, we’ll take a look at extending CharacterStyle to match our needs.

The key method of that abstract class is updateDrawState:



public abstract void updateDrawState(TextPaint tp);


Enter fullscreen mode Exit fullscreen mode

This method has as a parameter the TextPaint that will be used in our TextView. Most importantly, the TextPaint can have a shader object for drawing. And for that, we’ll be using LinearGradient shader!

The code

Without further ado, here’s what we came up with:

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView: TextView = findViewById(R.id.tv_hello)
val text = "Hello World!"
val purple = getColor(R.color.purple_200)
val teal = getColor(R.color.teal_200)
val spannable = text.toSpannable()
spannable[0..text.length] = LinearGradientSpan(text, text, purple, teal)
textView.text = spannable
}
}
view raw ExampleUsage.kt hosted with ❤ by GitHub
import android.graphics.LinearGradient
import android.graphics.Shader
import android.text.TextPaint
import android.text.style.CharacterStyle
import android.text.style.UpdateAppearance
import androidx.annotation.ColorInt
/**
* Applies a linear gradient on the text to which the span is attached.
*
* @param containingText The text that encloses the text that needs the gradient.
* @param textToStyle The text that the gradient will be applied on. Can be a substring of `containingText` or equal to `containingText`.
* @param startColorInt Resolved color to use as the gradient's start color.
* @param endColorInt Resolved color to use as the gradient's end color.
*/
class LinearGradientSpan(
private val containingText: String,
private val textToStyle: String,
@ColorInt private val startColorInt: Int,
@ColorInt private val endColorInt: Int
) : CharacterStyle(), UpdateAppearance {
override fun updateDrawState(tp: TextPaint?) {
tp ?: return
var leadingWidth = 0f
val indexOfTextToStyle = containingText.indexOf(textToStyle)
if (!containingText.startsWith(textToStyle) && containingText != textToStyle) {
leadingWidth = tp.measureText(containingText, 0, indexOfTextToStyle)
}
val gradientWidth = tp.measureText(containingText, indexOfTextToStyle, indexOfTextToStyle + textToStyle.length)
tp.shader = LinearGradient(
leadingWidth,
0f,
leadingWidth + gradientWidth,
0f,
startColorInt,
endColorInt,
Shader.TileMode.REPEAT
)
}
}

Using it

The LinearGradientSpan can be used as any other character style:



val textView: TextView = findViewById(R.id.tv_hello)
val text = "Hello World!"
val purple = getColor(R.color.purple_200)
val teal = getColor(R.color.teal_200)
val spannable = text.toSpannable()
spannable[0..text.length] = LinearGradientSpan(text, text, purple, teal)
textView.text = spannable


Enter fullscreen mode Exit fullscreen mode

It’s a relatively easy way to produce an interesting text effect.

hello_gradient

While in a more real scenario (taken from Plum’s android application) the effect can have a more subtle effect:

plum_gradient

Closing

As I’m not an expert in Graphics (let alone Android graphics 🤣), there should be plenty of optimizations that this utility class could receive. If you also want to build amazing things (and maybe improve the LinearGradientSpan!) check out our openings!

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay