Android Quote Span With AppCompat Support Using Both Java and Kotlin

Sourin Ghosh
The Startup
Published in
3 min readSep 18, 2020

My 1st publication on Medium, so I am starting off with a short and simple piece of implementation about a problem which I did not find an easy and straight forward solution on Stack Overflow or elsewhere.

Sample Quote Span

This is the easiest way to implement Android Quote Span with customized Stripe width and Gap width without writing your own Quote Span class while maintaining support for Android API level 27 and below. I am using a Parcel to pass the width parameters to the QuoteSpan object.

If we look at the QuoteSpan class there are 3 constructors apart from the default one and only one of them takes the Stripe width and Gap width parameters in case you need to customize the layout of the QuoteSpan.

public QuoteSpan(int color, int stripeWidth, int gapWidth) {
 throw new RuntimeException(“Stub!”);
 }

But when we try to use that constructor for our customized QuoteSpan we get an Error saying :

This constructor can only be used from API Level 28 and above
API Level 28+ supported only

This is because we want our Android Application to be supported up to a Minimum API Level of 23(Marshmallow) where as this is only supported from API Level 28(Pie) and above.

The usual thing was to search StackOverflow Android and other sites for an obvious solution. But the solutions I found were a bit complex as it required to copy the original QuoteSpan class from the SDK and then customize it with our own implementation which is what I did not want to do.

So I decided to experiment a bit and started to play around with the QuoteSpan code when I eventually found that the 4th constructor i.e. which accepts a Parcel object actually sets those Stripe Width and Gap Width parameters inside it.

public QuoteSpan(@NonNull Parcel src) {
 mColor = src.readInt();
 mStripeWidth = src.readInt();
 mGap

I implemented my customized QuoteSpan with the following Java code :

Parcel parcel = Parcel.obtain();
parcel.writeInt(getColor(R.color.colorAccent));//stripe color
parcel.writeInt(10);//stripe width
parcel.writeInt(10);//gap width
parcel.setDataPosition(0);
QuoteSpan quoteSpan = new QuoteSpan(parcel);
SpannableString string = new SpannableString(getString(R.string.top_review));
string.setSpan(quoteSpan, 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
((TextView) findViewById(R.id.quoteSpan)).setText(string);
parcel.recycle(); // put the parcel object back in the pool

And it worked like a charm with no Android API Level support issues 😀

Quote Span Android Preview

If you want to implement this using Kotlin then use this code :

val parcel = Parcel.obtain()
parcel.writeInt(getColor(R.color.colorAccent))//stripe color
parcel.writeInt(10)//stripe width
parcel.writeInt(10)//gap width
parcel.setDataPosition(0)
val quoteSpan = QuoteSpan(parcel)
val string = SpannableString(getString(R.string.top_review))
string.setSpan(quoteSpan, 0, string.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
findViewById<TextView>(R.id.quoteSpan).text = string
parcel.recycle() // put the parcel object back in the pool

Please find out the repository and sample Android Application in the following GitHub Link:

Please let me know in the comments if the article helped you or any suggestions you have for me.. Till then Happy Coding 👨‍💻✌

--

--