Android: TextView with multiples colors and fonts - android

Ok, so I gather that this should be a fairly straightforward process.
I've read the following questions:
Multiple Typefaces in the same TextView
Multiple Typefaces in the same TextView
Put in bold some parts of a TextView
Making part of a string bold in TextView
The advice seems to be pretty similar across all of these questions and answers. I'm trying to avoid the HTML techniques and use SpannableString and SpannableStringBuilder instead. Ultimately, I'd like to be able to use multiple different typefaces in a single TextView, but for now, I'd just like to figure out how to get multiple colors working.
I'm trying to implement those techniques in this way:
// Get a typeface for my custom font
String regularFontPath = "fonts/Abel-Regular.ttf";
Typeface regularTf = Typeface.createFromAsset(getActivity().getAssets(), regularFontPath);
// Set the label's typeface (this part is working)
mItemCodesLabel.setTypeface(regularTf);
// Create a spannable builder to build up my
// TextView's content from data
SpannableStringBuilder builder = new SpannableStringBuilder();
// These colors are defined and working well in other parts of my app
ForegroundColorSpan ltGraySpan = new ForegroundColorSpan(R.color.light_gray);
ForegroundColorSpan dkGraySpan = new ForegroundColorSpan(R.color.dark_gray);
// mCodesList has good data and the actual data output from this
// loop is correct. Just the styling is wrong
for (int i = 0; i < mCodesList.size(); i = i + 1) {
ParseObject code = mCodesList.get(i);
String value = code.getString("value") + " | ";
if (i > 0) {
// I want new codes to be on a new line (this works)
value = "\n" + value;
}
SpannableString valueSpan = new SpannableString(value);
valueSpan.setSpan(ltGraySpan, 0, value.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.append(valueSpan);
String loc = code.getString("location");
SpannableString locSpan = new SpannableString(loc);
locSpan.setSpan(dkGraySpan, 0, loc.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.append(locSpan);
}
mItemCodesLabel.setText(builder);
The net result is that the TextView contains the correct text contents. The TextView is the correct typeface. But the entire contents of the TextView are my #color/light_gray color. I'm not sure why, because in the XML layout file, I had specified my #color/dark_gray color (which I expect to be overridden by setting the text with a Spannable). Even if I change both ForegroundColorSpan objects to use R.color.dark_gray, the TextView still comes out light gray. I don't see anywhere else in my code where I'm setting the color of the text, so I'm really at a loss.
I'm running this on an LG Optimus G Pro, which is running 4.4.2. I have another TextView where I need to get multiple colors and font working and even underline some parts of the text, so this is a pretty big deal for me. Where am I going wrong?

use getResource().getColor(R.color.light_gray) to retrieve the color you are passing to the ForegroundColorSpan. I doubt it is retrieving it internally for you. You probably need to instantiate a new ForegroundColorSpan at every iteration. It is not possible to reuse it

You may Use SpannableStringBuilder because it implements from spannable and CharSequence, also you may do anything with following
TextView txtTest = (TextView) findViewById(R.id.txt);
String text = "This is an example";
final SpannableStringBuilder str = new SpannableStringBuilder(text);
str.setSpan(new TypefaceSpan("monospace"), 0, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new TypefaceSpan("serif"), 9, 12, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.white)), 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.grey)), 6, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
txtTest.setText(str);
I have add colors.xml in values
<color name="black">#000000</color>
<color name="grey">#DCDCDC</color>
<color name="white">#FFFFFF</color>

Related

Bold Text in TextView does not work with combination of Spanned and String

I have this code
TextView text1 = (TextView) view.findViewById(R.layout.myLayout);
Spanned myBold = (Html.fromHtml("<b>Test<b>", Html.FROM_HTML_MODE_LEGACY));
If I do
text1.setText(myBold);
Then myBold is in bold,which is ok. But when I want to add a string more, like
text1.setText(myBold+"bla");
Then the whole TextView is not bold anymore. Why does the new String "bla" affect this?
Thanks.
Why does the new String "bla" affect this?
Because what you are really doing is:
text1.setText(myBold.toString() + "bla");
A String has no style information. A Spanned object does.
Use TextUtils.concat() instead:
text1.setText(TextUtils.concat(myBold, "bla"));
A better choice would be to use a Bold StyleSpan. In the next sample only the "hello" world will be set to bold by using such technique:
Java:
final SpannableString caption = new SpannableString("hello world");
// Set to bold from index 0 to the length of 'hello'
caption.setSpan(new StyleSpan(Typeface.BOLD), 0, "hello".length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
yourTextView.setText(caption);
Kotlin:
yourTextView.text = SpannableString("hello world").apply {
// Set to bold from index 0 to the length of 'hello'
setSpan(StyleSpan(Typeface.BOLD), 0, "hello".length, Spannable.SPAN_INCLUSIVE_EXCLUSIVE))
}
This would be a more optimal solution rather than using the Html.fromHtml technicque, as it doesn't have to go through the overhead of parsing/interpreting the HTML tags.
In addition, it allows you to combine more styles, sizes, etc, in the same SpannableString.

Android. Has universal method for string text color for Android 4.0+?

Suppose I want to color part of text (words do you) in the
sentence.
So I use this:
<string name="congratulations">Hello, how <font color="#00FFFF">do you</font> do</string>
But this not work on Android 4.0.
So for fix this I use next:
<string name="congratulations">Hello, how <font fgcolor="#FF00FFFF">do you</font> do</string>
But this not work for Android 4.3.
Has universal approach that will be work for all Android 4.0+ version
AND for different languages?
I found that this not work on device: OS Version: 4.4.2
Device: HTC Desire 610. So at finally I use this solution:
<string name="expand"><![CDATA[<font color=#00FFFF>+</font> My contacts]]></string>.
Of course you need in java code use this:
Html.fromHtml(source);
So now it's work for all Adnroid 4.0+ and for all languages.
I've done something quite similar with SpannableString. look at this example:
String a = getString(R.string.string1);
String b = getString(R.string.string2);
Spanned color1 = setSpanColor(a,Color.CYAN);
Spanned color2 = setSpanColor(b,Color.RED);
Spanned mixedColor = TextUtils.concat(color1, " ", color2);
// Now use `mixedColor`
setSpanColor
public Spanned setSpanColor(String string, int color){
SpannableStringBuilder builder = new SpannableStringBuilder();
SpannableString ss = new SpannableString(string);
ss.setSpan(new ForegroundColorSpan(color), 0, string.length(), 0);
//ss.setSpan(new StyleSpan(Typeface.ITALIC), 0, string.length(), 0);
builder.append(ss);
return ss;
}
Update
Another way is to do it with Html format wich supports all API levels as well:
Spanned text;
String yourText = getResources().getString(R.string.congratulations);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
// For API 24(nougat)+
text =(Html.fromHtml("<font color='#FFEB3B'><b>"+yourText+"</b></font>",Html.FROM_HTML_MODE_LEGACY));
} else {
// pre API 24
text =(Html.fromHtml("<font color='#FFEB3B'><b>"+yourText+"</b></font>"));
}
// Now use `text`
Along #S.R answer you may Try dynamically. got from here
TextView TV = (TextView)findViewById(R.id.mytextview01);
Spannable wordtoSpan = new SpannableString("I know just how to whisper, And I know just how to cry,I know just where to find the answers");
wordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TV.setText(wordtoSpan);

Can i change span Text in android

Here is my code,i want to put two type of fonts in my Textview. I can successfully implement a code to do that.My problem is i want to edit the variable text without changing the arrangement.
String text = " my font1 , font 2 ";
Typeface font,font1;
font = Typeface.createFromAsset(getAssets(), "font.TTF");
font1 = Typeface.createFromAsset(getAssets(), "font1.TTF");
Spannable s = new SpannableString(text);
s.setSpan(new CustomTypefaceSpan("", font), curpos, endpos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
s.setSpan(new CustomTypefaceSpan("", font1), curpos, endpos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
.
.
.
.
//want to chage variable text here !
I reffered the following but i don't get the solution.
Set color of TextView span in Android
Android: Coloring part of a string using TextView.setText()?
TextView with different textSize
Try using the SpannableStringBuilder class. "This is the class for text whose content and markup can both be changed." It sounds like you need a mutable class.
It's unclear precisely how you want to change the text, but I use SpannableStringBuilder like this to insert additional text at the beginning of some text that is html. Once you have your string builder object there are sufficient methods available to modify things.
Spanned spHtml = Html.fromHtml(myHtmlString, Html.FROM_HTML_MODE_LEGACY);
SpannableStringBuilder sb = new SpannableStringBuilder(spHtml);
sb.insert(0, "text to be inserted");
Can you try something like this :
public void updateTextView(String toThis) {
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(toThis);
// Put here your span, ...
}
And call this function when you want update your textView

Function to return a spannable and append it to a string in textview

I am trying to create a function that will take a string "word" as an argument, apply span styling to the string and return it as a spannable string that I can ""+insert+"" into a string in a TextView. Thank you in advance for any help you can offer with this.
Here is the function I have so far.
public Spannable fr(String word){
Spannable WordtoSpan = new SpannableString(word);
WordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 0,
word.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
WordtoSpan.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0,
word.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return WordtoSpan;
}
and the code that should display the spannable inline with my text.
TextView tview = (TextView) findViewById(R.id.accents_view);
tview.setText(Html.fromHtml("<strong>Text String</strong> "+fr("style_this"));
The application will either load the text without styling or the app will crash. Not sure what I'm doing wrong but I'm guessing it has something to do with mixing fromHtml text with spannables. Any work arounds?
If I remove the Html.fromHtml() and wrap the entire text with my fr() function it works. I get bold blue text. But I need to be able to make only certain words styled... It would also be nice to be able to reference vars from my string.xml file instead of hard coding them in, for multilingual support.
I think you may find this helpful,
TextView tview = (TextView) findViewById(R.id.accents_view);
tview.setText(Html.fromHtml("<font color='blue'>Text</font> "
+ "<font color='red'>String</font>"));

Any way to set span directly to spanable text?

This may be a blunder,But I need to know... :)
Iam develeoping an android application,In in I want to display two type face in a single textview and found this One very useful,A custom typeface span that extends typeface span,
As per my understanding , we are creating a spannable as follows using two words
String firstWord = "first ";
String secondWord = "second";
// Create a new spannable with the two strings
Spannable spannable = new SpannableString(firstWord+secondWord);
then sets two type face to that words using our custom span like this
// Set the custom typeface to span over a section of the spannable object
spannable.setSpan( new CustomTypefaceSpan("sans-serif",CUSTOM_TYPEFACE), 0,
firstWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan( new CustomTypefaceSpan("sans-serif",SECOND_CUSTOM_TYPEFACE), rstWord.length(), secondWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Now my question, I have a large amount of text so If i am able to put the spans directly in my text its will be a more easy for us ,is that possible to put spans directly to the text like we put <b>bold </b> as my need is to use my custom typeface span like <typeface1> sample </typeface1> <typeface2> Doc </typeface2>.
WHAT I NEED IS, DIRECTLY APPLY THE CHANGE TO TEXT WHAT THE SET SPAN DO TO THE TEXT
Is that possible, if possible what i need to write as span in my text,How can I achieve this.. or am i compleatly wrong ?
Thank you for all
Very late answer but what you asked for is pretty easy.
For instance, lets say we want to change everything between quotation marks into italic font.
String s = "\"Hello my name is Edward\" Hola, my nombre es Edward";
Pattern p = Pattern.compile("\"([^\"]*)\"");
Matcher m = p.matcher(text);
Spannable spannable = new SpannableString(s);
while (m.find()) {
int textLocation = text.indexOf(m.group(1));
// Set the custom typeface to span over a section of the spannable object
spannable.setSpan( new CustomTypefaceSpan("sans-serif",my_italic_font),
textLocation-1, textLocation + m.group(1).length(),spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// Set the text of a textView with the spannable object
TextView textbox = (TextView) v.findViewById(R.id.cardtextbox);
}
textbox.setText( spannable );
Result of s would be
"Hello my name is Edward" Hola, my nombre es Edward
Now instead of quotation marks you would use a regex pattern for tags like <b>bold </b>;
And you could also remove the tags afterwards with a simple .replace();

Categories

Resources