Skip to content

Instantly share code, notes, and snippets.

@cmargonis
Last active May 4, 2022 09:35
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cmargonis/d1822422ac3f604b97ec06757ff351cd to your computer and use it in GitHub Desktop.
Save cmargonis/d1822422ac3f604b97ec06757ff351cd to your computer and use it in GitHub Desktop.
Gradient span which can be applied to an Android TextView
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
}
}
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
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment