Android — replace the specific span of TextView with a drawable
When you want to display text with icons as one TextView like below, how do you achieve it?
One simple approach is to constraint three components: TextView of “Press” and ImageView of camera drawable, and TaxtView of “please!!”.
But what happens when you need to support different languages with string resources, like below?
You may notice that the position of drawable depends on each language, so that aligning three views may make you struggle because you have to adjust the alignment according to each language.
Use SpannableString and ImageSpan
So what approach will be good in this case?
SpannableString and ImageSpan will be one of the solutions.
Span that replaces the text it’s attached to with a
Drawable
that can be aligned with the bottom or with the baseline of the surrounding text.
In this case, if you need two languages: Engish and Japanese, make string values like below.
// value/strings
<string name="explanation">Press cameraIcon please!!</string>// value-ja/strings
<string name=”explanation”>cameraIconをタップしてね!</string>
The cameraIcon is the span that will be replaced with a drawable.
Below is the flow of replacing the word “cameraIcon” with a drawable.
To designate the span area, first, you need to get the start position of the span.
val string = resources.getString(R.string.explanation)
val spanText = "cameraIcon"
val startPosition = string.split(spanText)[0].length
Then, get the end position of the span.
val endPosition = startPosition + spanText.length
Finally, replace the span with a resource.
val ss = SpannableString(string)
val drawable = ContextCompat.getDrawable(this, R.drawable.ic_photo)
val lineHeight = textView.lineHeight
drawable!!.setBounds(0,0,lineHeight, lineHeight) // adjust the size of resource so that the resource fit with the sorrouncing text size.ss.setSpan(ImageSpan(drawable), startPosition, endPosition, SPAN_EXCLUSIVE_EXCLUSIVE)
textView.text = ss
That’s all !!
After this, you do not have to care about using different languages as long as you use the mark text “cameraIcon”.
GitHub sample code is here.