SpannableStringBuilder append a SpannableString object not show the span? - android

I am trying to use the SpannableStringBuilder to implement spannable color to all occurrence of a given character sequence in the sentence, just like:
val spannableStr1 = SpannableString("hello world!")
spannableStr1.setSpan(ForegroundColorSpan(Color.parseColor("#FF0000")),
0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
val spannableBuilder = SpannableStringBuilder()
spannableBuilder.append(spannableStr1)
spannableBuilder.append(spannableStr1)
tvDemo.text = spannableBuilder
and this resulted to:
I need the second occurrence of the characters hel also in red color. So I tried to append spannableStr1 again, but it seems not working.
Is there any way to implement it?

The span on spannableStr1 is set for 0-3. Unfortunately once you add it to the spannable string builder the second time, it's still 0-3. This causes the problem here- you colored the same part red twice.
A better way of doing this is not to add spans to the text. Instead, just append the text and add the spans directly to the SpannableStringBuilder. This means the first span should be (0,3) and the second one should be (index of second h, index of second h + 3)
val spannableStr1 ="hello world!"
val spannableBuilder = SpannableStringBuilder()
spannableBuilder.append(spannableStr1)
spannableBuilder.append(spannableStr1)
spannableBuilder.setSpan(ForegroundColorSpan(Color.parseColor("#FF0000")),
0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
spannableBuilder.setSpan(ForegroundColorSpan(Color.parseColor("#FF0000")),
spannableStr1.length, spannableStr1.length + 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
tvDemo.text = spannableBuilder

Related

How to change color of a TextView line by line?

I have text that goes like that:
loading item 1
loading item 2
loading item 3
I want to change color (or fontWeight) of every line to show user the progress.
You can use SpannableString for this
val currentText = textView.text
val spannable = SpannableString(currentText)
spannable.setSpan(ForegroundColorSpan(Color.RED), 0, endOfFirstLine, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
spannable.setSpan(ForegroundColorSpan(Color.GREEN), endOfFirstLine, endOfSecondLine, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
spannable.setSpan(ForegroundColorSpan(Color.YELLOW), endOfSecondLine, endOfThirdLine, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
// Set the colored text
textView.text = spannable

Setting "same" styles to several parts of text

I have styles (e.g., BackgroundColorSpan) and I'd like to set it to multiple parts of the texts. But if the same instance of BackgroundColorSpan, etc. is assigned to other part of the text, the style moves.
E.g.,
Object HighlightStyle = new BackgroundColorSpan(Color.argb(255, 255, 215, 0));
TextView X = (TextView) findViewById(R.id.Text);
SpannableStringBuilder SpannableBuilder = new SpannableStringBuilder();
SpannableBuilder.append("1");
SpannableBuilder.setSpan(HighlightStyle, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // This is hilited
SpannableBuilder.append("2");
SpannableBuilder.setSpan(HighlightStyle, 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // This is hilited and 1 is no more hilited
SpannableBuilder.append("3");
SpannableBuilder.append("4");
SpannableBuilder.setSpan(HighlightStyle, 3, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // This is hilited and 1 and 2 are no more hilited
X.setText(SpannableBuilder);
// I want hilited 1,2,4 all at the same time
Why I do it ? A user can search for some text and that text should be highlighted.
How I'd like to do it ? All text is in a single TextView. I have a single SpannableStringBuilder. I have a method that breaks the text into parts - String and Boolean. String is part, Boolean says whether the text is matched - should be highligted - or not. I just pass, e.g., instance of BackgroundColorSpan into that method and it should be applied to every part that was matched but because of the behavior of setSpan, only last part is highlighted.
Potential solutions: Style doesn't implement .clone method. I could make a workaround like serialize/deserialize it to create new instances but that seems really like a hack.
Is there some elegant way how to set the same style to X parts of the text ?
You should create new HighlightStyle object each time when you call setSpan(), you can do this with the next method:
CharacterStyle.wrap()
With all changes your code will be the next:
SpannableStringBuilder SpannableBuilder = new SpannableStringBuilder();
SpannableBuilder.append("1");
SpannableBuilder.setSpan(CharacterStyle.wrap(HighlightStyle), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
SpannableBuilder.append("2");
SpannableBuilder.setSpan(CharacterStyle.wrap(HighlightStyle), 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
SpannableBuilder.append("3");
SpannableBuilder.append("4");
SpannableBuilder.setSpan(CharacterStyle.wrap(HighlightStyle), 3, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
This is how it looks in my Application:

In TextInputLayout change the color of hint for single letter or alphabet

I have defined TextInputLayout programmatically in my Activity. I have added EditText inside that TextInputLayout, that to programmatically.
Now, I have to set the color of hint of that edittext. Here I just have to change the color of single alphabet of the hint.
Example - Hint is like, Firstname *. Here i want to change the color of "*" to Red and remaining hint as black in color.
I have already tried Html and Spannable String, but both are not working for TextInputLayout.
For Spannable i did
SpannableString redSpannable = new SpannableString(red);
redSpannable.setSpan(new ForegroundColorSpan(Color.RED), 0, red.length(), 0);
Spanned hint = Html.fromHtml(string + redSpannable);
etDefault[j].setHint(hint);
For HTML,
I used "font-color"
If anyone knows this, then share your opinion.
As per the Android Issue Tracker,
Setting the hint to the editText respects the span, but the label does
not float on focus.
editText.setHint(hint);
Setting the hint to the textInputLayout ignores the span
textInputLayout.setHint(hint);
TextInputLayout uses internal class CollapsingTextHelper to draw the
hint, which does not support spans.
And as they said,
They have passed this defect on to the development team and will
update this issue with more information as it becomes available.
In TextInputLayout change the color of hint for single letter or alphabet
String firstNameText ="firstName *";
Spanned redStar;
String html = "<string style=\"color:firstNameText;\">firstName<span style=\"color:red;\">*</span></string>";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.L) {
redStar = Html.fromHtml(html,Html.FROM_HTML_MODE_LEGACY);
} else {
redStar = Html.fromHtml(html);
}
I suggest you using just SpannableStringBuilder without Html.fromHtml:
SpannableStringBuilder sb = new SpannableStringBuilder("Hint with first letter black");
CharacterStyle cs= new ForegroundColorSpan(ContextCompat.getColor(this, android.R.color.black));
sb.setSpan(cs, 0, 1, 0);
((TextView) findViewById(R.id.description_messages)).setHint(sb);
In this piece of code the first letter becomes black. If you would like it to be bold too, use this:
CharacterStyle cs = new StyleSpan(android.graphics.Typeface.BOLD);
That just puts hint to EditText. There will be no floating text effect.

Spannable style isn't applying

So, i'm having a message which contains text and SpannableStringBuilder which is initialized like this :
final SpannableStringBuilder builder = new SpannableStringBuilder(message.getMessage());
And by default, i'm setting font to BOLD :
builder.setSpan(new StyleSpan(Typeface.BOLD), 0, messageText.length(), 0);
But my message text will be changed, example :
Your question : {question}
Your answer : {answer}
{question} and {answer} are objects that will be replaced with text, replacing is happening like this:
final TextObject question = objects.getQuestion();
spannable = new SpannableString(question.getText());
spannable.setSpan(new StyleSpan(Typeface.NORMAL), 0, spannable.length(), 0);
builder.replace(start, end, spannable);
Text is replacing just fine, but NORMAL font type isn't applying to it, so i have all text BOLD, but i need this parts to be normal
Any help is highly appreciated
You have to add that Spanned.SPAN_INCLUSIVE_INCLUSIVE as a last parameter
spannable.setSpan(new StyleSpan(Typeface.NORMAL), 0, spannable.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
and if you want some part in bold and some not you have to be specific which part. The second and the third parameter of setSpan method is responsible for that

android: increase width width of quotespan strip

i am using quoteSpan for a textView
SpannableString t1 = new SpannableString(Html.fromHtml(myItems.get(position).getTest()));
t1.setSpan(new QuoteSpan(Color.RED), 0, t1.length(), Spannable.SPAN_PARAGRAPH);
txtView1.setText(t1);
but it displays a very very thin line on the left of the text, is there any way to make this line thicker so that it looks better?
Use the Quote Span class constructor that accepts a Parcel and use this 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
If you want in Kotlin see this Repository :
Custom Android Quote Span with AppCompat support

Categories

Resources