Spannable string with control character - android

I want to show a text in a TextView with different colors and put control characters to break lines \n and tabs \t\t...
I do this...
SpannableStringBuilder sb = new SpannableStringBuilder("");
ForegroundColorSpan fcs_red = new ForegroundColorSpan(Color.RED);
ForegroundColorSpan fcs_blu = new ForegroundColorSpan(Color.BLUE);
...
for(int j = 0; j < columns.length; j++)
{
if(columns[j].equals("<")) continue;
if(columns[j].contains("/") && columns[j].contains(":"))
{
columns[j] = columns[j].replace("<TD>", "\n");
sb_aux = new SpannableStringBuilder(columns[j]);
sb_aux.setSpan(fcs_red, 0, sb_aux.length(),Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
else
{
if(columns[j].contains("<TD>"))
{
columns[j] = columns[j].replace("<TD>", "\n\t\t");
sb_aux = new SpannableStringBuilder(columns[j]);
sb_aux.setSpan(fcs_blu, 0, sb_aux.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
else
{
columns[j] = "\n\t\t"+columns[j];
sb_aux = new SpannableStringBuilder(columns[j]);
sb_aux.setSpan(fcs_blu, 0, sb_aux.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
}
sb.append(sb_aux);
}
myTextView.setText(sb);
So, the first part of text is showed in RED as expected, but the rest of text do not alternate in RED or BLUE as expected and the \n and \t was not recognized
My intention was spanning text in pieces and appending to a SpannableStringBuilder to be showed in TextView, any clues ?

Using the following code you can show rich text in a TextView.
String html = "<font color='red'>This is red</font>" +
"<br/>new line \t some indent <b>BOLD</b>";
myTextView.setText(Html.fromHtml(html));

Related

How to change the colour of the word that start from the # in the string and show it in textview

Hi guys I want to change the colour of specific words that are starts from the # or # in the string just like abc#yahoo.com i want to change all the character that is after and also show it into textview #
String[] parts=str.split(" ");
for (int i = 0; i < parts.length; i++) {
if(parts[i].startsWith("#") || parts[i].startsWith("#"))
{
System.out.println(part[i]);
}
this will give me tokens but i want to show the whole string with modify words
try to use below given code
String[] parts=str.split(" ");
for (int i = 0; i < parts.length; i++) {
if(parts[i].startsWith("#") || parts[i].startsWith("#"))
{
System.out.println(Html.fromHtml("<font color='red'>part[i]</font>"));
}
Hopefully it will perfectly work for you.
textView = ((TextView) view.findViewById(R.id.textView));
SpannableStringBuilder ss = new SpannableStringBuilder();
String stringText = "# #dfdfg df#dgh fh# # #fdf fdf#fdf fdf#";
String[] stringArray = stringText.split(" ");
Pattern pattern = Pattern.compile("^[#|#](\\w+|)");//starting with # or # and text after
Matcher patternMatcher = null;
for (int i = 0; i < stringArray.length; i++) {
patternMatcher = pattern.matcher(stringArray[i]);
if (patternMatcher.find()) {
SpannableString spannableString = new SpannableString(patternMatcher.group());
spannableString.setSpan(new ForegroundColorSpan(Color.BLUE), 0, patternMatcher.group().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.append(spannableString);
} else {
ss.append(stringArray[i]);
}
if (i + 1 < stringArray.length)//add space only when this is not the end
ss.append(" ");
}
if (patternMatcher != null)
patternMatcher.reset();
textView.setText(ss);
Split this String into array with '#' and space.
Use Spannable Text for change the colour of special words.
Please refer this link to change the color of words : Set color of TextView span in Android

How to change some character color in TextView

I know that I can change color of the part of TextView with Spannable, I use this for changing color of every character 'e' in text. But I got this error:
java.lang.IndexOutOfBoundsException: setSpan (55 ... 56) ends beyond
length 0
My code:
aye="My Text has been written today";
SpannableString spantext=new SpannableString(aye);
for (int i=0;i<aye.length();i++) {
if (aye.contains("e")) {
a+=aye.indexOf("e", a)+1;
spantext.setSpan(new ForegroundColorSpan(Color.RED), a, a+1, 0);
holder.tv_arabic.setText(spantext);
}
}
Any way?
Try this:
aye="My Text has been written today";
String newText = aye.replace("e", "<font color=#FF0000>e</font>");
holder.tv_arabic.setText(Html.fromHtml(newText));
Original idea from https://stackoverflow.com/a/6094346/3922891
I have faced the same problem.Following is my code.You can follow this example in your code:
String aye = "My Text has been written today";
String ayeTemp = "My Text has been written today";
ArrayList<Integer> positionInt = new ArrayList<>();
for (int i = 0; i < ayeTemp.length(); i++) {
if (ayeTemp.contains("e")) {
if (positionInt.size() == 0) {
positionInt.add(ayeTemp.indexOf("e"));
} else {
positionInt.add(positionInt.get(positionInt.size() - 1) + ayeTemp.indexOf("e") + 1);
}
ayeTemp = ayeTemp.substring(ayeTemp.indexOf("e") + 1, ayeTemp.length() - 1);
} else {
break;
}
}
Spannable wordtoSpan = new SpannableString(aye);
for (int i = 0; i < positionInt.size(); i++) {
wordtoSpan.setSpan(new ForegroundColorSpan(Color.RED), positionInt.get(i), positionInt.get(i) + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
holder.tv_arabic.setText(wordtoSpan);
like this

Android ColorSpannot working if same text exists

I have used following code to set color to a text in Text view.It works fine excepts if same text contains 2 or more times.That is if the text contains" #abc #abc" first #abc is displayed only in red color.Please help me.
SpannableString ss = new SpannableString(Title);
final String[] str_array = Title.split(" ");
for (int i = 0; i < str_array.length; i++) {
if (str_array[i].startsWith("#")) {
ss.setSpan(
new ForegroundColorSpan(mcontext.getResources()
.getColor(R.color.red)),
Title.indexOf(str_array[i]),
Title.indexOf(str_array[i])
+ (str_array[i].length()),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
The problem is because you are using String.indexOf() method which returns:
indexOf(String): searches in this string for the first index of the specified string.
Therefore when you pass in #abc #abc it will always return 0 and will not apply the span to the second substring.
To solve this, you should use indexOf(string, offset) where you specify the offset. See the following code:
SpannableString ss = new SpannableString(Title);
final String[] str_array = Title.split(" ");
int lastOffset = 0;
for (int i = 0; i < str_array.length; i++) {
if (str_array[i].startsWith("#")) {
int startPosition = Title.indexOf(str_array[i], lastOffset);
int endPosition = startPosition + (str_array[i].length());
ss.setSpan(new ForegroundColorSpan(Color.RED),
startPosition, endPosition,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
lastOffset = endPosition;
}
}
Explanation:
Everytime you apply a span to a string, update the value of lastOffset so that the indexOf(string, offset) will return the next substring instead of always returning the first one.
If it's only to set colors to your text you could use the following method:
Html.fromHtml()
and pass in necessary html tags.
textView.setText(Html.fromHtml("<font color=\"#145A14\">text</font>"));
This should work, make sure to add check for index out of bound errors in case String is just #a:
String Title = "#abs #abc";
int length = "#abc".length();
SpannableString ss = new SpannableString(Title);
int start = Title.indexOf("#", 0);
while (start != -1) {
ss.setSpan(new ForegroundColorSpan(mcontext.getResources()
.getColor(R.color.red)), start, start + length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
start = Title.indexOf("#", start + 1);
}

change android textview color from a string

Hey i am creating a android textview which contains come from json..
It is fine but i want to change color of the part of the text view.. dont know how
here is my details-
JSONArray jArray= new JSONArray(result);
for(int i=0; i<jArray.length();i++)
{
JSONObject getjson=jArray.getJSONObject(i);
s= "Title: " +getjson.getString("tender_title")+
"\n\nTender id: " +getjson.getString("tender_id")+
"\n\nReference no:\n"+getjson.getString("tender_reference_no")+
"\n\nQuantity: " +getjson.getString("tender_item_details_quantity");
}
TextView txt=(TextView) findViewById(R.id.textView1);
txt.setText(s);
On the above code is fine..that sets all the value in the text view but i want to change the color of "Title" ,"Tender id", "Quantity" etc.. from above string s please help
You can set the text as html:
txt.setText(Html.fromHtml("your <font color='#FF0000'>content</font>");
Use spans
Example:
{
final SpannableStringBuilder sb = new SpannableStringBuilder("your text here");
final ForegroundColorSpan fcs = new ForegroundColorSpan(Color.rgb(158, 158, 158));
// Span to set text color to some RGB value
final StyleSpan bss = new StyleSpan(android.graphics.Typeface.BOLD);
// Span to make text bold
sb.setSpan(fcs, 0, 4, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
// Set the text color for first 4 characters
sb.setSpan(bss, 0, 4, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
// make them also bold
yourTextView.setText(sb);
}
Here is a solution specific to your case:
Update your code as follows:
JSONArray jArray= new JSONArray(result);
Spanned spannedStr = null;
for(int i=0; i<jArray.length();i++)
{
JSONObject getjson = jArray.getJSONObject(i);
spannedStr = (Spanned) TextUtils.concat(getColorString("Title:"), getjson.getString("tender_title"), "\n\n",
getColorString("Tender id:"), getjson.getString("tender_title"), "\n\n",
getColorString("Reference no:"), getjson.getString("tender_title"), "\n\n",
getColorString("Quantity:"), getjson.getString("tender_title"));
}
TextView txt=(TextView) findViewById(R.id.textView1);
txt.setText(spannedStr);
Define a helper method in the same class and use it:
private Spanned getColorString(String str) {
return Html.fromHtml("<font color='#FFFF00'>" + str + "</font>");
}
Sample output:
you can use Spanned also for that.
Spanned sText=Html.fromHtml("<font color="#C3003">Title:</font> " );
txt.setText(sText);
Spannable WordtoSpan = new SpannableString(text);
WordtoSpan.setSpan(new ForegroundColorSpan(Color.WHITE), text.length, (text +
nextString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
myTextView.setText(WordtoSpan);

Change text color of one word in a TextView

I am looking for a way to change the color of a text of a single word in a TextView from within an Activity.
For example, with this:
String first = "This word is ";
String next = "red"
TextView t = (TextView) findViewById(R.id.textbox);
t.setText(first + next);
How would I change the color of the next text to red?
Easiest way I know is to just use html.
String first = "This word is ";
String next = "<font color='#EE0000'>red</font>";
t.setText(Html.fromHtml(first + next));
But this will require you to rebuild the TextView when (if?) you want to change the color, which could cause a hassle.
t.setText(first + next, BufferType.SPANNABLE);
Spannable s = (Spannable)t.getText();
int start = first.length();
int end = start + next.length();
s.setSpan(new ForegroundColorSpan(0xFFFF0000), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
you have to use spannable this will also allows you to increase some text's size, make it bold etc.... even put in some image.
Use SpannableStringBuilder like this :
SpannableStringBuilder builder = new SpannableStringBuilder();
SpannableString str1= new SpannableString("Text1");
str1.setSpan(new ForegroundColorSpan(Color.RED), 0, str1.length(), 0);
builder.append(str1);
SpannableString str2= new SpannableString(appMode.toString());
str2.setSpan(new ForegroundColorSpan(Color.GREEN), 0, str2.length(), 0);
builder.append(str2);
TextView tv = (TextView) view.findViewById(android.R.id.text1);
tv.setText( builder, TextView.BufferType.SPANNABLE);
for long string you can use this:
String help = getString(R.string.help);
help = help.replace("some word", "<font color='#EE0000'>some word</font>");
txtDesc.setText(Html.fromHtml(help));
If you want to change the state of all the instances of a specific String inside a TextView text(case insensitive) you can use StringBuilders and SpannableString like this:
StringBuilder textBuilder = new StringBuilder(myTextView.getText().toString());
StringBuilder searchedTextBuilder = new StringBuilder((mySearchedString));
SpannableString spannableString = new SpannableString(myTextView.getText().toString());
int counter = 0;
int index = 0;
for (int i = 0;i < textBuilder.length() - mySearchedString.length() - 1;i++)
{
counter = 0;
if (Character.toLowerCase(textBuilder.charAt(i)) == Character.toLowerCase(searchedTextBuilder.charAt(index)))
{
counter++;
index++;
for (int j = 1,z = i + 1;j < mySearchedString.length() - 1;j++,z++)
{
if (Character.toLowerCase(textBuilder .charAt(z)) == Character.toLowerCase(searchedTextBuilder .charAt(index)))
{
counter++;
index++;
}
else
{
index++;
if (index % mySearchedString.length() == 0)
{
index = 0;
}
break;
}
}
if (counter == mySearchedString.length() - 1) // A match
{
spannableString.setSpan(new ForegroundColorSpan(Color.RED), i,
i + mySearchedString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // Do the change you want(In this case changing the fore ground color to red)
index = 0;
continue;
}
else
{
index = 0;
continue;
}
}
}
myTextView.setText(spannableString);
}
Store the whole TextView text inside a StringBuilder.
Store the searched string inside a StringBuilder.
Store the wholre TextView text inside a SpannableString
Make a simple operation to find all the String instances inside the TextView text and change them when reached.
Set the text value of the TextView to the SpannableString.
I implemented a utility function in Kotlin for my own usecase and maybe useful for someone else.
fun getCusomTextWithSpecificTextWithDiffColor(textToBold: String, fullText: String,
targetColor: Int) =
SpannableStringBuilder(fullText).apply {
setSpan(ForegroundColorSpan(targetColor),
fullText.indexOf(textToBold),
(fullText.indexOf(textToBold) + textToBold.length),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
How I am using it:
context?.let {
infoMessage.text = AppUtils.getCusomTextWithSpecificTextWithDiffColor(
wordAsBold,
completeSentence, ContextCompat.getColor(it, R.color.white))
}
USE:
makeTextBold("Your order is accepted","accepted", textView);
makeTextBold("Your order is canceled","canceled", textView);
Function:
public static void makeTextBold(String sentence, String word, AppCompatTextView textView) {
SpannableStringBuilder builder = new SpannableStringBuilder();
int startIndex = sentence.indexOf(word.toLowerCase().trim());
int endIndex = startIndex + word.toLowerCase().trim().length();
SpannableString spannableString = new SpannableString(sentence);
StyleSpan boldSpan = new StyleSpan(Typeface.BOLD);
spannableString.setSpan(boldSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //To make text Bold
spannableString.setSpan(new ForegroundColorSpan(Color.RED), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //To change color of text
builder.append(spannableString);
textView.setText(builder, TextView.BufferType.SPANNABLE);
}
I think this is more readable
for coloring a word in a string
it is also probably more efficient a bit because you write once
String str = YOUR_STRING
Spannable s = new SpannableString(str);
int start = str.indexOf(err_word_origin);
int end = start + err_word_origin.length();
s.setSpan(new ForegroundColorSpan(Color.BLUE), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
YOUR_TEXT_VIEW.setText(s , TextView.BufferType.SPANNABLE);
my solution extension:
fun coloredText(
baseText: String,
coloredText: String,
targetColor: Int
): SpannableStringBuilder {
val transformText = "$baseText $coloredText"
return SpannableStringBuilder(transformText).apply {
setSpan(
ForegroundColorSpan(targetColor),
transformText.indexOf(coloredText),
(transformText.indexOf(coloredText) + coloredText.length),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
Usage
binding.mytextView.title = coloredText(
baseText = getString(R.string.my_title),
coloredText = getString(R.string.my_title_colored_part),
targetColor = ContextCompat.getColor(requireContext(), R.color.blue))
Iv'e found this best answer
https://stackoverflow.com/a/53573169/14250778
just changed one line to support also words that starts with uppercase letter
public void setHighLightedText(TextView tv, String textToHighlight) {
// added "toLowerCase()" to support words that starts with uppercase letter
String tvt = tv.getText().toString().toLowerCase();
int ofe = tvt.indexOf(textToHighlight, 0);
Spannable wordToSpan = new SpannableString(tv.getText());
for (int ofs = 0; ofs < tvt.length() && ofe != -1; ofs = ofe + 1) {
ofe = tvt.indexOf(textToHighlight, ofs);
if (ofe == -1)
break;
else {
// set color here
wordToSpan.setSpan(new BackgroundColorSpan(0xFFFFFF00), ofe, ofe + textToHighlight.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(wordToSpan, TextView.BufferType.SPANNABLE);
}
}
}

Categories

Resources