Related
I don't know how to make a specific text on TextView become BOLD.
its like this
txtResult.setText(id+" "+name);
I want the output to be like this:
1111 neil
id and name are variables that I have retrieved the value from database, and I want to make the id to bold, but only the id so the name will not affected, I have no idea how to do this.
Just build your String in HTML and set it:
String sourceString = "<b>" + id + "</b> " + name;
mytextview.setText(Html.fromHtml(sourceString));
While you can use Html.fromHtml() you can use a more native approach which is SpannableStringBuilder , this post may be helful.
SpannableStringBuilder str = new SpannableStringBuilder("Your awesome text");
str.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), INT_START, INT_END, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView tv=new TextView(context);
tv.setText(str);
First: You don't need to worry about using the slow performance code from the Raghav Sood's answer.
Second: You don't need to write an extension function provided by w3bshark's answer when using Kotlin.
Finnaly: All you need to do is to use the Kotlin android-ktx library from Google (refer here to find more information and how to include it on your project):
// Suppose id = 1111 and name = neil (just what you want).
val s = SpannableStringBuilder()
.bold { append(id) }
.append(name)
txtResult.setText(s)
Produces: 1111 neil
UPDATE:
Because I think it can help someone else as well as to demonstrate how far you can go here are more use cases.
When you need to display a text with some parts in blue and italic:
val myCustomizedString = SpannableStringBuilder()
.color(blueColor, { append("A blue text ") })
.append("showing that ")
.italic{ append("it is painless") }
When you need to display a text in both bold and italic:
bold { italic { append("Bold and italic") } }
In short, bold, append, color and italic are extension functions to SpannableStringBuilder. You can see another extension functions in the official documentation, from where you can think for other possibilities.
I thought that the chosen answer didn't provide a satisfactory result. I have written my own function which takes 2 strings; The full text and the part of the text you want to make bold.
It returns a SpannableStringBuilder with the 'textToBold' from 'text' bolded.
I find the ability to make a substring bold without wrapping it in tags useful.
/**
* Makes a substring of a string bold.
* #param text Full text
* #param textToBold Text you want to make bold
* #return String with bold substring
*/
public static SpannableStringBuilder makeSectionOfTextBold(String text, String textToBold){
SpannableStringBuilder builder=new SpannableStringBuilder();
if(textToBold.length() > 0 && !textToBold.trim().equals("")){
//for counting start/end indexes
String testText = text.toLowerCase(Locale.US);
String testTextToBold = textToBold.toLowerCase(Locale.US);
int startingIndex = testText.indexOf(testTextToBold);
int endingIndex = startingIndex + testTextToBold.length();
//for counting start/end indexes
if(startingIndex < 0 || endingIndex <0){
return builder.append(text);
}
else if(startingIndex >= 0 && endingIndex >=0){
builder.append(text);
builder.setSpan(new StyleSpan(Typeface.BOLD), startingIndex, endingIndex, 0);
}
}else{
return builder.append(text);
}
return builder;
}
As wtsang02 said, using HTML is an expensive overhead. Just use the native solution. If you don't have to modify the string, just use SpannableString, not SpannableStringBuilder.
String boldText = "id";
String normalText = "name";
SpannableString str = new SpannableString(boldText + normalText);
str.setSpan(new StyleSpan(Typeface.BOLD), 0, boldText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(str);
In case you want to use the string from XML, you can do something like this:
strings.xml (the "CDATA" part is important, otherwise it won't work)
<string name="test">
<![CDATA[
<b>bold!</b> normal
]]>
</string>
layout file
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
<TextView
android:id="#+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
code
textView.text = HtmlCompat.fromHtml(getString(R.string.test), HtmlCompat.FROM_HTML_MODE_LEGACY)
Its simple just close the specified text like this for example <b>"your text here:"</b>
<string name="headquarters">"<b>"Headquarters:"</b>" Mooresville, North Carolina, U.S.</string>
result:
Headquarters: Mooresville, North Carolina, U.S.
If you are using Kotlin, it becomes even easier to do by using core-ktx, as it provides a domain-specific-language (DSL) for doing this:
val string: SpannedString = buildSpannedString {
bold {
append("foo")
}
append("bar")
}
More options provided by it are:
append("Hello There")
bold {
append("bold")
italic {
append("bold and italic")
underline {
append("then some text with underline")
}
}
}
At last, you can just to:
textView.text = string
Based on #mladj0ni's answer, I got the code below to work. The problem was that if you use String.format, it strips out the html markup, so you have to escape the bracket symbols in strings.xml:
strings.xml:
<string name="welcome_messages">Hello, %1$s! You have <b>%2$d new messages</b>.</string>
code.java:
String unspanned = String.format(Locale.US, "%s%s", getResources().getString(R.string. welcome_messages), 99);
Spanned spanned;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
spanned = Html.fromHtml(unspanned, Html.FROM_HTML_MODE_LEGACY);
} else {
spanned = Html.fromHtml(unspanned);
}
textView.setText(spanned);
It's simpler than SpannableStringBuilder. As for performance, if you're displaying just one string, then the user won't notice the extra millisecond to parse it.
See the documentation here.
Here is better solution if you want to make multiple text to bold. I've improved Eitan's code. thanks Eitan.
public static SpannableStringBuilder makeSectionOfTextBold(String text, String... textToBold) {
SpannableStringBuilder builder = new SpannableStringBuilder(text);
for (String textItem :
textToBold) {
if (textItem.length() > 0 && !textItem.trim().equals("")) {
//for counting start/end indexes
String testText = text.toLowerCase(Locale.US);
String testTextToBold = textItem.toLowerCase(Locale.US);
int startingIndex = testText.indexOf(testTextToBold);
int endingIndex = startingIndex + testTextToBold.length();
if (startingIndex >= 0 && endingIndex >= 0) {
builder.setSpan(new StyleSpan(Typeface.BOLD), startingIndex, endingIndex, 0);
}
}
}
return builder;
}
You can use this code to set part of your text to bold. For whatever is in between the bold html tags, it will make it bold.
String myText = "make this <b>bold</b> and <b>this</b> too";
textView.setText(makeSpannable(myText, "<b>(.+?)</b>", "<b>", "</b>"));
public SpannableStringBuilder makeSpannable(String text, String regex, String startTag, String endTag) {
StringBuffer sb = new StringBuffer();
SpannableStringBuilder spannable = new SpannableStringBuilder();
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
sb.setLength(0);
String group = matcher.group();
String spanText = group.substring(startTag.length(), group.length() - endTag.length());
matcher.appendReplacement(sb, spanText);
spannable.append(sb.toString());
int start = spannable.length() - spanText.length();
spannable.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), start, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
sb.setLength(0);
matcher.appendTail(sb);
spannable.append(sb.toString());
return spannable;
}
wtsang02 answer is the best way to go about it, since, Html.fromHtml("") is now deprecated. Here I'm just going to enhance it a little bit for whoever is having problem in dynamically making the first word bold, no matter whats the size of the sentence.
First lets create a method to get the first word:
private String getFirstWord(String input){
for(int i = 0; i < input.length(); i++){
if(input.charAt(i) == ' '){
return input.substring(0, i);
}
}
return input;
}
Now let's say you have a long string like this:
String sentence = "friendsAwesomeName#gmail.com want's to be your friend!"
And you want your sentence to be like yourAwesomeName#gmail.com want's to be your friend!
All you have to do is- get the firstWord and get the lenght of it to make the firstWord bold, something like this:
String myFirstWord = getFirstWord(sentence);
int start = 0; // bold will start at index 0
int end = myFirstWord.length(); // and will finish at whatever the length of your first word
Now just follow wtsang02 's steps, like this:
SpannableStringBuilder fancySentence = new SpannableStringBuilder(sentence);
fancySentence.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(fancySentence);
And that's it! Now you should be able to bold a word with any size from long/short sentence.
I came here to provide a more up-to-date solution, because I wasn't satisfied with the existing answers.
I needed something that would work for translated texts and does not have the performance hit of using Html.fromHtml().
If you're using Kotlin, here is an extension function which will easily set multiple parts of your text to bold. This works just like Markdown, and could be extended to support other Markdown tags, if need be.
val yourString = "**This** is your **string**.".makePartialTextsBold()
val anotherString = getString(R.string.something).makePartialTextsBold()
/**
* This function requires that the parts of the string that need
* to be bolded are wrapped in ** and ** tags
*/
fun String.makePartialTextsBold(): SpannableStringBuilder {
var copy = this
return SpannableStringBuilder().apply {
var setSpan = true
var next: String
do {
setSpan = !setSpan
next = if (length == 0) copy.substringBefore("**", "") else copy.substringBefore("**")
val start = length
append(next)
if (setSpan) {
setSpan(StyleSpan(Typeface.BOLD), start, length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
copy = copy.removePrefix(next).removePrefix("**")
} while (copy.isNotEmpty())
}
}
Here is my complete solution for dynamic String values with case check.
/**
* Makes a portion of String formatted in BOLD.
*
* #param completeString String from which a portion needs to be extracted and formatted.<br> eg. I am BOLD.
* #param targetStringToFormat Target String value to format. <br>eg. BOLD
* #param matchCase Match by target character case or not. If true, BOLD != bold
* #return A string with a portion formatted in BOLD. <br> I am <b>BOLD</b>.
*/
public static SpannableStringBuilder formatAStringPortionInBold(String completeString, String targetStringToFormat, boolean matchCase) {
//Null complete string return empty
if (TextUtils.isEmpty(completeString)) {
return new SpannableStringBuilder("");
}
SpannableStringBuilder str = new SpannableStringBuilder(completeString);
int start_index = 0;
//if matchCase is true, match exact string
if (matchCase) {
if (TextUtils.isEmpty(targetStringToFormat) || !completeString.contains(targetStringToFormat)) {
return str;
}
start_index = str.toString().indexOf(targetStringToFormat);
} else {
//else find in lower cases
if (TextUtils.isEmpty(targetStringToFormat) || !completeString.toLowerCase().contains(targetStringToFormat.toLowerCase())) {
return str;
}
start_index = str.toString().toLowerCase().indexOf(targetStringToFormat.toLowerCase());
}
int end_index = start_index + targetStringToFormat.length();
str.setSpan(new StyleSpan(BOLD), start_index, end_index, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return str;
}
Eg. completeString = "I am BOLD"
CASE I
if *targetStringToFormat* = "bold" and *matchCase* = true
returns "I am BOLD" (since bold != BOLD)
CASE II
if *targetStringToFormat* = "bold" and *matchCase* = false
returns "I am BOLD"
To Apply:
myTextView.setText(formatAStringPortionInBold("I am BOLD", "bold", false))
Hope that helps!
I used this code to bold specific words...
Spanned string = Html.fromHtml("Normal string <b>BOLD STRING</b>");
textView.setText(string);
Isn't this code the easiest solution?
<string name="string">Please provide your <b>Name</b> properly</string>
Just use this string whatever you want :)
The result will like this:
Please provide your Name properly
public static Spanned getBoldString(String textNotBoldFirst, String textToBold, String textNotBoldLast) {
String resultant = null;
resultant = textNotBoldFirst + " " + "<b>" + textToBold + "</b>" + " " + textNotBoldLast;
return Html.fromHtml(resultant);
}
Try this. It can help definitely
Make first char of string spannable while searching for char in list/recycler like
ravi and ajay
previously highlighting like this but i wanted to be like below
ravi and ajay OR ravi and ajay
for this I searched for word length if it is equal to 1 ,I separated main string into words and calculated word start position then I searched word starting with char.
public static SpannableString colorString(int color, String text, String... wordsToColor) {
SpannableString coloredString = new SpannableString(text);
for (String word : wordsToColor) {
Log.e("tokentoken", "-wrd len-" + word.length());
if (word.length() !=1) {
int startColorIndex = text.toLowerCase().indexOf(word.toLowerCase());
int endColorIndex = startColorIndex + word.length();
try {
coloredString.setSpan(new ForegroundColorSpan(color), startColorIndex, endColorIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception e) {
e.getMessage();
}
} else {
int start = 0;
for (String token : text.split("[\u00A0 \n]")) {
if (token.length() > 0) {
start = text.indexOf(token, start);
// Log.e("tokentoken", "-token-" + token + " --start--" + start);
char x = token.toLowerCase().charAt(0);
char w = word.toLowerCase().charAt(0);
// Log.e("tokentoken", "-w-" + w + " --x--" + x);
if (x == w) {
// int startColorIndex = text.toLowerCase().indexOf(word.toLowerCase());
int endColorIndex = start + word.length();
try {
coloredString.setSpan(new ForegroundColorSpan(color), start, endColorIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception e) {
e.getMessage();
}
}
}
}
}
}
return coloredString;
}
You can add the two strings separately in the builder, one of them is spannedString, the other is a regular one.This way you don`t have to calculate the indexes.
val instructionPress = resources?.getString(R.string.settings_press)
val okText = resources?.getString(R.string.ok)
val spannableString = SpannableString(okText)
val spannableBuilder = SpannableStringBuilder()
spannableBuilder.append(instructionPress)
spannableBuilder.append(spannableString, StyleSpan(Typeface.BOLD), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
instructionText.setText(spannableBuilder,TextView.BufferType.SPANNABLE)
This is the Kotlin extension function I use for this
/**
* Sets the specified Typeface Style on the first instance of the specified substring(s)
* #param one or more [Pair] of [String] and [Typeface] style (e.g. BOLD, ITALIC, etc.)
*/
fun TextView.setSubstringTypeface(vararg textsToStyle: Pair<String, Int>) {
val spannableString = SpannableString(this.text)
for (textToStyle in textsToStyle) {
val startIndex = this.text.toString().indexOf(textToStyle.first)
val endIndex = startIndex + textToStyle.first.length
if (startIndex >= 0) {
spannableString.setSpan(
StyleSpan(textToStyle.second),
startIndex,
endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
this.setText(spannableString, TextView.BufferType.SPANNABLE)
}
Usage:
text_view.text="something bold"
text_view.setSubstringTypeface(
Pair(
"something bold",
Typeface.BOLD
)
)
.
text_view.text="something bold something italic"
text_view.setSubstringTypeface(
Pair(
"something bold ",
Typeface.BOLD
),
Pair(
"something italic",
Typeface.ITALIC
)
)
if the position of bold text is fixed(ex: if is at start of the textView), then use two different textView with same background. Then you can make the other textView's textStyle as bold.
This will require twice the memory compared to a single textView but speed will increase.
Found a way in case you want to handle localization in multiple languages, it's boring to do but it works, let's suppose we want this:
In English:
There are no payments registered
In Spanish:
No hay pagos registrados
You have to create 3 strings
English:
<string name="start_string">There are no</string>
<string name="middle_string">payments</string>
<string name="end_string">registered.</string>
<string name="string_format" translatable="false">%1$s %2$s %3$s</string>
Spanish:
<string name="start_string">No hay</string>
<string name="middle_string">pagos</string>
<string name="end_string">registrados</string>
Now you can do this:
val startSpanPosition = getString(R.string.start_string).length
val endSpanPosition = startSpanPosition + getString(R.string.middle_string).length
val mySpannableString = SpannableStringBuilder(String.format(getString(R.string.string_format),
getString(R.string.start_string), getString(R.string.middle_string))), getString(R.string.end_string)))
mySpannableString.setSpan(StyleSpan(Typeface.BOLD), spanStartPosition, endSpanPosition, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
Your String resource
<resources>
<string name="your_string_resource_name">This is normal text<![CDATA[<b> but this is bold </b>]]> and <![CDATA[<u> but this is underline text</u>]]></string>
</resources>
your java class
yourtextView.setText(getString(R.string.your_string_resource_name));
I have created a static method for setting part of text Bold for TextView and EditText
public static void boldPartOfText(View mView, String contentData, int startIndex, int endIndex){
if(!contentData.isEmpty() && contentData.length() > endIndex) {
final SpannableStringBuilder sb = new SpannableStringBuilder(contentData);
final StyleSpan bss = new StyleSpan(Typeface.BOLD); // Span to make text bold
final StyleSpan iss = new StyleSpan(Typeface.NORMAL); //Span to make text normal
sb.setSpan(iss, 0, startIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
sb.setSpan(bss, startIndex, endIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold
sb.setSpan(iss,endIndex, contentData.length()-1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
if(mView instanceof TextView)
((TextView) mView).setText(sb);
else if(mView instanceof EditText)
((EditText) mView).setText(sb);
}
}
Another more customized code
/*typeFaceStyle can be passed as
Typeface.NORMAL = 0;
Typeface.BOLD = 1;
Typeface.ITALIC = 2;
Typeface.BOLD_ITALIC = 3;*/
public static void boldPartOfText(View mView, String contentData, int startIndex, int endIndex,int typeFaceStyle){
if(!contentData.isEmpty() && contentData.length() > endIndex) {
final SpannableStringBuilder sb = new SpannableStringBuilder(contentData);
final StyleSpan bss = new StyleSpan(typeFaceStyle); // Span to make text bold
final StyleSpan iss = new StyleSpan(Typeface.NORMAL); //Span to make text italic
sb.setSpan(iss, 0, startIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
sb.setSpan(bss, startIndex, endIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold
sb.setSpan(iss,endIndex,contentData.length()-1,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
if(mView instanceof TextView)
((TextView) mView).setText(sb);
else if(mView instanceof EditText)
((EditText) mView).setText(sb);
}
}
In case someone is using Data Binding. We can define binding adapter like this
#BindingAdapter("html")
fun setHtml(view: TextView, html: String) {
view.setText(HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY))
}
Then we can use it on a TextView
app:html="#{#string/bold_text}"
where bold_text is
<string name="bold_text"><![CDATA[Part of text is <b>bold</b>]]></string>
Simple Example
In you strings.xml
<string name="str_privacy_policy">This is our Privacy Policy.</string>
if you want to make specifically "Privacy Policy" as bold put the string between the bold tags.
Like this
<string name="str_privacy_policy">This is our <b>Privacy Policy.</b></string>
Result would be
This is our Privacy Policy
Here's how I do it using regular expressions and Kotlin
val BOLD_SPAN = StyleSpan(Typeface.BOLD)
fun TextView.boldMatches(regexString: String) {
this.applyStyleSpanToMatches(regexString, BOLD_SPAN)
}
fun TextView.applyStyleSpanToMatches(regexString: String, span: StyleSpan){
this.text = this.text.toString().applyStyleSpanToMatches(regexString, span)
}
fun String.applyStyleSpanToMatches(regexString: String, span: StyleSpan): Spannable {
val result = SpannableString.valueOf(this)
if(regexString.isEmpty()) return result
val pattern = try{
Pattern.compile(regexString)
} catch (e: PatternSyntaxException){
return result
}
val matcher = pattern.matcher(result)
while (matcher.find()) {
val start = matcher.start()
val end = matcher.end()
result.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
return result
}
using the question
it can be applied like this:
txtResult.boldMatches(id)
If you are using Kotlin and string resources, a simple solution is:
Create your string on strings.xml, using <b> </b> to bold the parts you want
<string name="my_message"> This is a very <b>important</b> message! </string>
On Kotlin code you must do like so
textView.setText(R.string.my_message)
And that is it!
Important note!
Using property syntax will not work:
textView.text = resources.getString(R.string.my_message)
Hope it helps!
val phone = "+45xxxxxx"
val phoneText = "<font color=#757B7F><b>${phone}</b></font>"
val wholeString = requireActivity().resources.getString(R.string.loginwith)+" "+phoneText
Just add this in your tag
dangerouslySetInnerHTML={{__html: "<p>Your html text here.<p>"}}
I am unable to get text in an AlertDialog to display in bold or italic.
I've tried formatting directly and also using the CharSequence utilties from the Android string-resource page but I always get just plain text.
What am I doing wrong?
MyFragment.java
String idFormatted = String.format(resources.getString(R.string.id));
CharSequence idStyledText = Html.fromHtml(idFormatted);
CharSequence nameItalic = Utilities.italic(resources.getString(R.string.name));
String typeFormatted = String.format(resources.getString(R.string.type));
CharSequence typeStyledText = Html.fromHtml(idFormatted);
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setPositiveButton("Dismiss",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
}).setIcon(android.R.drawable.ic_dialog_info);
builder.setMessage( idFormatted + myData.getId() + "\t\t" + nameItalic + myData.getName() + "\t\t" + typeFormatted + myData.getType() );
Dialog dialog = builder.create();
dialog.setTitle("Details");
dialog.show();
strings.xml
<string name="id"><i>Id: </i></string>
<string name="name"><i>Name: </i></string>
<string name="type"><i>Type: </i></string>
Edit: -------------------------------------------------------------
Mohammad Arman suggests that the strings from the string.xml will not retain the html. This seems likely to be true, though I can't prove it yet.
Based on his and Farbod Salamat-Zadeh's answer, I tried the code below, but still the result is the same, just plain text.
Spanned idLabel = Html.fromHtml("<i>" + resources.getString(R.string.id) + "</i>");
Spanned nameLabel = Html.fromHtml("<i>" + resources.getString(R.string.name) + "</i>");
Spanned typeLabel = Html.fromHtml("<i>" + resources.getString(R.string.type) + "</i>");
...
builder.setMessage(idLabel.toString() + myData.getId() + "\t\t" + nameLabel + myData.getName());
Edit2: -----------------------------------------------------------
I've tried as Keelan has suggested:
<string name="italic_string"><![CDATA[<i>italic-string</i>]]></string>
and then:
String formattedText = getString(R.string.italic_string);
Spanned result = Html.fromHtml(formattedText);
builder.setMessage(result);
This works.
You can't simply store HTML in a strings.xml file. You need to put them in CDATA, like so:
<string name="id"><![CDATA[<i>Id: </i>]]></string>
Then to display a formatted string, you still need to use Html.fromHtml().
You can get text anywhere to display in bold or italic - I use the following;
Spanned italicText = Html.fromHtml("<i>" + "My italic text" + "</i>");
Spanned boldText = Html.fromHtml("<b>" + "My boldtext" + "</b>");
// You can use different HTML tags depending on what you want.
You need to format the html version in a separate String variable in Java class (otherwise for some reason it won't work).
String myId = <i>Id: </i>;
String myName = <b>Name: </b>
Then you have to add this in the textView like bellow:
textView1.setText(Html.fromHtml(myId +" "+ "1234");
textView2.setText(Html.fromHtml(myName +" "+ "Al Lelopath")
Why your approach is not working
It's because as you are importing the string from string.xml it will lose the attribute and send it as a plain text. And that's why Android could not take that as html.
I am appending String to Editbox.
here appendToMessageHistory is method.
I want to set separate separate color for the Both String Username and messge
please give solution before you vote down and think it is not relevent in android.
public void appendToMessageHistory(String username, String message) {
if (username != null && message != null) {
messageHistoryText.append(username + ":");
messageHistoryText.append(message + "\n" + "\n");
}
}
any suggestion is appreciated.
String htmlText = "<font color=#cccccc>" + username+"</font> <font color=#ffeecc>"+ message+"</font>";
messageHistoryText.setText(Html.fromHtml(htmlText));
Try this hope it will help.
public static Spanned fromHtml (String source)
Try using SpannableString.
SpannableString spannableString = new SpannableString(editText.getText().toString());
int lastIndex = //index to be used
spannableString.setSpan(new ForegroundColorSpan(Color.BLUE),0,lastIndex, 0);
editText.setText(spannableString);
Check this nice Tutorial.
I don't know how to make a specific text on TextView become BOLD.
its like this
txtResult.setText(id+" "+name);
I want the output to be like this:
1111 neil
id and name are variables that I have retrieved the value from database, and I want to make the id to bold, but only the id so the name will not affected, I have no idea how to do this.
Just build your String in HTML and set it:
String sourceString = "<b>" + id + "</b> " + name;
mytextview.setText(Html.fromHtml(sourceString));
While you can use Html.fromHtml() you can use a more native approach which is SpannableStringBuilder , this post may be helful.
SpannableStringBuilder str = new SpannableStringBuilder("Your awesome text");
str.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), INT_START, INT_END, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView tv=new TextView(context);
tv.setText(str);
First: You don't need to worry about using the slow performance code from the Raghav Sood's answer.
Second: You don't need to write an extension function provided by w3bshark's answer when using Kotlin.
Finnaly: All you need to do is to use the Kotlin android-ktx library from Google (refer here to find more information and how to include it on your project):
// Suppose id = 1111 and name = neil (just what you want).
val s = SpannableStringBuilder()
.bold { append(id) }
.append(name)
txtResult.setText(s)
Produces: 1111 neil
UPDATE:
Because I think it can help someone else as well as to demonstrate how far you can go here are more use cases.
When you need to display a text with some parts in blue and italic:
val myCustomizedString = SpannableStringBuilder()
.color(blueColor, { append("A blue text ") })
.append("showing that ")
.italic{ append("it is painless") }
When you need to display a text in both bold and italic:
bold { italic { append("Bold and italic") } }
In short, bold, append, color and italic are extension functions to SpannableStringBuilder. You can see another extension functions in the official documentation, from where you can think for other possibilities.
I thought that the chosen answer didn't provide a satisfactory result. I have written my own function which takes 2 strings; The full text and the part of the text you want to make bold.
It returns a SpannableStringBuilder with the 'textToBold' from 'text' bolded.
I find the ability to make a substring bold without wrapping it in tags useful.
/**
* Makes a substring of a string bold.
* #param text Full text
* #param textToBold Text you want to make bold
* #return String with bold substring
*/
public static SpannableStringBuilder makeSectionOfTextBold(String text, String textToBold){
SpannableStringBuilder builder=new SpannableStringBuilder();
if(textToBold.length() > 0 && !textToBold.trim().equals("")){
//for counting start/end indexes
String testText = text.toLowerCase(Locale.US);
String testTextToBold = textToBold.toLowerCase(Locale.US);
int startingIndex = testText.indexOf(testTextToBold);
int endingIndex = startingIndex + testTextToBold.length();
//for counting start/end indexes
if(startingIndex < 0 || endingIndex <0){
return builder.append(text);
}
else if(startingIndex >= 0 && endingIndex >=0){
builder.append(text);
builder.setSpan(new StyleSpan(Typeface.BOLD), startingIndex, endingIndex, 0);
}
}else{
return builder.append(text);
}
return builder;
}
As wtsang02 said, using HTML is an expensive overhead. Just use the native solution. If you don't have to modify the string, just use SpannableString, not SpannableStringBuilder.
String boldText = "id";
String normalText = "name";
SpannableString str = new SpannableString(boldText + normalText);
str.setSpan(new StyleSpan(Typeface.BOLD), 0, boldText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(str);
In case you want to use the string from XML, you can do something like this:
strings.xml (the "CDATA" part is important, otherwise it won't work)
<string name="test">
<![CDATA[
<b>bold!</b> normal
]]>
</string>
layout file
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
<TextView
android:id="#+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
code
textView.text = HtmlCompat.fromHtml(getString(R.string.test), HtmlCompat.FROM_HTML_MODE_LEGACY)
Its simple just close the specified text like this for example <b>"your text here:"</b>
<string name="headquarters">"<b>"Headquarters:"</b>" Mooresville, North Carolina, U.S.</string>
result:
Headquarters: Mooresville, North Carolina, U.S.
If you are using Kotlin, it becomes even easier to do by using core-ktx, as it provides a domain-specific-language (DSL) for doing this:
val string: SpannedString = buildSpannedString {
bold {
append("foo")
}
append("bar")
}
More options provided by it are:
append("Hello There")
bold {
append("bold")
italic {
append("bold and italic")
underline {
append("then some text with underline")
}
}
}
At last, you can just to:
textView.text = string
Based on #mladj0ni's answer, I got the code below to work. The problem was that if you use String.format, it strips out the html markup, so you have to escape the bracket symbols in strings.xml:
strings.xml:
<string name="welcome_messages">Hello, %1$s! You have <b>%2$d new messages</b>.</string>
code.java:
String unspanned = String.format(Locale.US, "%s%s", getResources().getString(R.string. welcome_messages), 99);
Spanned spanned;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
spanned = Html.fromHtml(unspanned, Html.FROM_HTML_MODE_LEGACY);
} else {
spanned = Html.fromHtml(unspanned);
}
textView.setText(spanned);
It's simpler than SpannableStringBuilder. As for performance, if you're displaying just one string, then the user won't notice the extra millisecond to parse it.
See the documentation here.
Here is better solution if you want to make multiple text to bold. I've improved Eitan's code. thanks Eitan.
public static SpannableStringBuilder makeSectionOfTextBold(String text, String... textToBold) {
SpannableStringBuilder builder = new SpannableStringBuilder(text);
for (String textItem :
textToBold) {
if (textItem.length() > 0 && !textItem.trim().equals("")) {
//for counting start/end indexes
String testText = text.toLowerCase(Locale.US);
String testTextToBold = textItem.toLowerCase(Locale.US);
int startingIndex = testText.indexOf(testTextToBold);
int endingIndex = startingIndex + testTextToBold.length();
if (startingIndex >= 0 && endingIndex >= 0) {
builder.setSpan(new StyleSpan(Typeface.BOLD), startingIndex, endingIndex, 0);
}
}
}
return builder;
}
You can use this code to set part of your text to bold. For whatever is in between the bold html tags, it will make it bold.
String myText = "make this <b>bold</b> and <b>this</b> too";
textView.setText(makeSpannable(myText, "<b>(.+?)</b>", "<b>", "</b>"));
public SpannableStringBuilder makeSpannable(String text, String regex, String startTag, String endTag) {
StringBuffer sb = new StringBuffer();
SpannableStringBuilder spannable = new SpannableStringBuilder();
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
sb.setLength(0);
String group = matcher.group();
String spanText = group.substring(startTag.length(), group.length() - endTag.length());
matcher.appendReplacement(sb, spanText);
spannable.append(sb.toString());
int start = spannable.length() - spanText.length();
spannable.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), start, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
sb.setLength(0);
matcher.appendTail(sb);
spannable.append(sb.toString());
return spannable;
}
wtsang02 answer is the best way to go about it, since, Html.fromHtml("") is now deprecated. Here I'm just going to enhance it a little bit for whoever is having problem in dynamically making the first word bold, no matter whats the size of the sentence.
First lets create a method to get the first word:
private String getFirstWord(String input){
for(int i = 0; i < input.length(); i++){
if(input.charAt(i) == ' '){
return input.substring(0, i);
}
}
return input;
}
Now let's say you have a long string like this:
String sentence = "friendsAwesomeName#gmail.com want's to be your friend!"
And you want your sentence to be like yourAwesomeName#gmail.com want's to be your friend!
All you have to do is- get the firstWord and get the lenght of it to make the firstWord bold, something like this:
String myFirstWord = getFirstWord(sentence);
int start = 0; // bold will start at index 0
int end = myFirstWord.length(); // and will finish at whatever the length of your first word
Now just follow wtsang02 's steps, like this:
SpannableStringBuilder fancySentence = new SpannableStringBuilder(sentence);
fancySentence.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(fancySentence);
And that's it! Now you should be able to bold a word with any size from long/short sentence.
Isn't this code the easiest solution?
<string name="string">Please provide your <b>Name</b> properly</string>
Just use this string whatever you want :)
The result will like this:
Please provide your Name properly
I came here to provide a more up-to-date solution, because I wasn't satisfied with the existing answers.
I needed something that would work for translated texts and does not have the performance hit of using Html.fromHtml().
If you're using Kotlin, here is an extension function which will easily set multiple parts of your text to bold. This works just like Markdown, and could be extended to support other Markdown tags, if need be.
val yourString = "**This** is your **string**.".makePartialTextsBold()
val anotherString = getString(R.string.something).makePartialTextsBold()
/**
* This function requires that the parts of the string that need
* to be bolded are wrapped in ** and ** tags
*/
fun String.makePartialTextsBold(): SpannableStringBuilder {
var copy = this
return SpannableStringBuilder().apply {
var setSpan = true
var next: String
do {
setSpan = !setSpan
next = if (length == 0) copy.substringBefore("**", "") else copy.substringBefore("**")
val start = length
append(next)
if (setSpan) {
setSpan(StyleSpan(Typeface.BOLD), start, length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
copy = copy.removePrefix(next).removePrefix("**")
} while (copy.isNotEmpty())
}
}
Here is my complete solution for dynamic String values with case check.
/**
* Makes a portion of String formatted in BOLD.
*
* #param completeString String from which a portion needs to be extracted and formatted.<br> eg. I am BOLD.
* #param targetStringToFormat Target String value to format. <br>eg. BOLD
* #param matchCase Match by target character case or not. If true, BOLD != bold
* #return A string with a portion formatted in BOLD. <br> I am <b>BOLD</b>.
*/
public static SpannableStringBuilder formatAStringPortionInBold(String completeString, String targetStringToFormat, boolean matchCase) {
//Null complete string return empty
if (TextUtils.isEmpty(completeString)) {
return new SpannableStringBuilder("");
}
SpannableStringBuilder str = new SpannableStringBuilder(completeString);
int start_index = 0;
//if matchCase is true, match exact string
if (matchCase) {
if (TextUtils.isEmpty(targetStringToFormat) || !completeString.contains(targetStringToFormat)) {
return str;
}
start_index = str.toString().indexOf(targetStringToFormat);
} else {
//else find in lower cases
if (TextUtils.isEmpty(targetStringToFormat) || !completeString.toLowerCase().contains(targetStringToFormat.toLowerCase())) {
return str;
}
start_index = str.toString().toLowerCase().indexOf(targetStringToFormat.toLowerCase());
}
int end_index = start_index + targetStringToFormat.length();
str.setSpan(new StyleSpan(BOLD), start_index, end_index, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return str;
}
Eg. completeString = "I am BOLD"
CASE I
if *targetStringToFormat* = "bold" and *matchCase* = true
returns "I am BOLD" (since bold != BOLD)
CASE II
if *targetStringToFormat* = "bold" and *matchCase* = false
returns "I am BOLD"
To Apply:
myTextView.setText(formatAStringPortionInBold("I am BOLD", "bold", false))
Hope that helps!
I used this code to bold specific words...
Spanned string = Html.fromHtml("Normal string <b>BOLD STRING</b>");
textView.setText(string);
public static Spanned getBoldString(String textNotBoldFirst, String textToBold, String textNotBoldLast) {
String resultant = null;
resultant = textNotBoldFirst + " " + "<b>" + textToBold + "</b>" + " " + textNotBoldLast;
return Html.fromHtml(resultant);
}
Try this. It can help definitely
Make first char of string spannable while searching for char in list/recycler like
ravi and ajay
previously highlighting like this but i wanted to be like below
ravi and ajay OR ravi and ajay
for this I searched for word length if it is equal to 1 ,I separated main string into words and calculated word start position then I searched word starting with char.
public static SpannableString colorString(int color, String text, String... wordsToColor) {
SpannableString coloredString = new SpannableString(text);
for (String word : wordsToColor) {
Log.e("tokentoken", "-wrd len-" + word.length());
if (word.length() !=1) {
int startColorIndex = text.toLowerCase().indexOf(word.toLowerCase());
int endColorIndex = startColorIndex + word.length();
try {
coloredString.setSpan(new ForegroundColorSpan(color), startColorIndex, endColorIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception e) {
e.getMessage();
}
} else {
int start = 0;
for (String token : text.split("[\u00A0 \n]")) {
if (token.length() > 0) {
start = text.indexOf(token, start);
// Log.e("tokentoken", "-token-" + token + " --start--" + start);
char x = token.toLowerCase().charAt(0);
char w = word.toLowerCase().charAt(0);
// Log.e("tokentoken", "-w-" + w + " --x--" + x);
if (x == w) {
// int startColorIndex = text.toLowerCase().indexOf(word.toLowerCase());
int endColorIndex = start + word.length();
try {
coloredString.setSpan(new ForegroundColorSpan(color), start, endColorIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception e) {
e.getMessage();
}
}
}
}
}
}
return coloredString;
}
You can add the two strings separately in the builder, one of them is spannedString, the other is a regular one.This way you don`t have to calculate the indexes.
val instructionPress = resources?.getString(R.string.settings_press)
val okText = resources?.getString(R.string.ok)
val spannableString = SpannableString(okText)
val spannableBuilder = SpannableStringBuilder()
spannableBuilder.append(instructionPress)
spannableBuilder.append(spannableString, StyleSpan(Typeface.BOLD), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
instructionText.setText(spannableBuilder,TextView.BufferType.SPANNABLE)
This is the Kotlin extension function I use for this
/**
* Sets the specified Typeface Style on the first instance of the specified substring(s)
* #param one or more [Pair] of [String] and [Typeface] style (e.g. BOLD, ITALIC, etc.)
*/
fun TextView.setSubstringTypeface(vararg textsToStyle: Pair<String, Int>) {
val spannableString = SpannableString(this.text)
for (textToStyle in textsToStyle) {
val startIndex = this.text.toString().indexOf(textToStyle.first)
val endIndex = startIndex + textToStyle.first.length
if (startIndex >= 0) {
spannableString.setSpan(
StyleSpan(textToStyle.second),
startIndex,
endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
this.setText(spannableString, TextView.BufferType.SPANNABLE)
}
Usage:
text_view.text="something bold"
text_view.setSubstringTypeface(
Pair(
"something bold",
Typeface.BOLD
)
)
.
text_view.text="something bold something italic"
text_view.setSubstringTypeface(
Pair(
"something bold ",
Typeface.BOLD
),
Pair(
"something italic",
Typeface.ITALIC
)
)
if the position of bold text is fixed(ex: if is at start of the textView), then use two different textView with same background. Then you can make the other textView's textStyle as bold.
This will require twice the memory compared to a single textView but speed will increase.
Found a way in case you want to handle localization in multiple languages, it's boring to do but it works, let's suppose we want this:
In English:
There are no payments registered
In Spanish:
No hay pagos registrados
You have to create 3 strings
English:
<string name="start_string">There are no</string>
<string name="middle_string">payments</string>
<string name="end_string">registered.</string>
<string name="string_format" translatable="false">%1$s %2$s %3$s</string>
Spanish:
<string name="start_string">No hay</string>
<string name="middle_string">pagos</string>
<string name="end_string">registrados</string>
Now you can do this:
val startSpanPosition = getString(R.string.start_string).length
val endSpanPosition = startSpanPosition + getString(R.string.middle_string).length
val mySpannableString = SpannableStringBuilder(String.format(getString(R.string.string_format),
getString(R.string.start_string), getString(R.string.middle_string))), getString(R.string.end_string)))
mySpannableString.setSpan(StyleSpan(Typeface.BOLD), spanStartPosition, endSpanPosition, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
Your String resource
<resources>
<string name="your_string_resource_name">This is normal text<![CDATA[<b> but this is bold </b>]]> and <![CDATA[<u> but this is underline text</u>]]></string>
</resources>
your java class
yourtextView.setText(getString(R.string.your_string_resource_name));
I have created a static method for setting part of text Bold for TextView and EditText
public static void boldPartOfText(View mView, String contentData, int startIndex, int endIndex){
if(!contentData.isEmpty() && contentData.length() > endIndex) {
final SpannableStringBuilder sb = new SpannableStringBuilder(contentData);
final StyleSpan bss = new StyleSpan(Typeface.BOLD); // Span to make text bold
final StyleSpan iss = new StyleSpan(Typeface.NORMAL); //Span to make text normal
sb.setSpan(iss, 0, startIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
sb.setSpan(bss, startIndex, endIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold
sb.setSpan(iss,endIndex, contentData.length()-1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
if(mView instanceof TextView)
((TextView) mView).setText(sb);
else if(mView instanceof EditText)
((EditText) mView).setText(sb);
}
}
Another more customized code
/*typeFaceStyle can be passed as
Typeface.NORMAL = 0;
Typeface.BOLD = 1;
Typeface.ITALIC = 2;
Typeface.BOLD_ITALIC = 3;*/
public static void boldPartOfText(View mView, String contentData, int startIndex, int endIndex,int typeFaceStyle){
if(!contentData.isEmpty() && contentData.length() > endIndex) {
final SpannableStringBuilder sb = new SpannableStringBuilder(contentData);
final StyleSpan bss = new StyleSpan(typeFaceStyle); // Span to make text bold
final StyleSpan iss = new StyleSpan(Typeface.NORMAL); //Span to make text italic
sb.setSpan(iss, 0, startIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
sb.setSpan(bss, startIndex, endIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold
sb.setSpan(iss,endIndex,contentData.length()-1,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
if(mView instanceof TextView)
((TextView) mView).setText(sb);
else if(mView instanceof EditText)
((EditText) mView).setText(sb);
}
}
In case someone is using Data Binding. We can define binding adapter like this
#BindingAdapter("html")
fun setHtml(view: TextView, html: String) {
view.setText(HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY))
}
Then we can use it on a TextView
app:html="#{#string/bold_text}"
where bold_text is
<string name="bold_text"><![CDATA[Part of text is <b>bold</b>]]></string>
Simple Example
In you strings.xml
<string name="str_privacy_policy">This is our Privacy Policy.</string>
if you want to make specifically "Privacy Policy" as bold put the string between the bold tags.
Like this
<string name="str_privacy_policy">This is our <b>Privacy Policy.</b></string>
Result would be
This is our Privacy Policy
Here's how I do it using regular expressions and Kotlin
val BOLD_SPAN = StyleSpan(Typeface.BOLD)
fun TextView.boldMatches(regexString: String) {
this.applyStyleSpanToMatches(regexString, BOLD_SPAN)
}
fun TextView.applyStyleSpanToMatches(regexString: String, span: StyleSpan){
this.text = this.text.toString().applyStyleSpanToMatches(regexString, span)
}
fun String.applyStyleSpanToMatches(regexString: String, span: StyleSpan): Spannable {
val result = SpannableString.valueOf(this)
if(regexString.isEmpty()) return result
val pattern = try{
Pattern.compile(regexString)
} catch (e: PatternSyntaxException){
return result
}
val matcher = pattern.matcher(result)
while (matcher.find()) {
val start = matcher.start()
val end = matcher.end()
result.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
return result
}
using the question
it can be applied like this:
txtResult.boldMatches(id)
If you are using Kotlin and string resources, a simple solution is:
Create your string on strings.xml, using <b> </b> to bold the parts you want
<string name="my_message"> This is a very <b>important</b> message! </string>
On Kotlin code you must do like so
textView.setText(R.string.my_message)
And that is it!
Important note!
Using property syntax will not work:
textView.text = resources.getString(R.string.my_message)
Hope it helps!
val phone = "+45xxxxxx"
val phoneText = "<font color=#757B7F><b>${phone}</b></font>"
val wholeString = requireActivity().resources.getString(R.string.loginwith)+" "+phoneText
Just add this in your tag
dangerouslySetInnerHTML={{__html: "<p>Your html text here.<p>"}}
I have same info String like...
String info1 ="yyy";
String info2 ="mmm";
Now I want to disply it in Html Format and bold As..
Our First Information:yyy
Our Second Information:mmm
Below is example for the same.
textview.setText(
Html.fromHtml(
"<b>" +info1 + "</b> " + "<font color=\"#000000\">" +
info2 +
"</font>"+
""));
String info1 ="yyy"; String info2 ="mmm";
etmsg.setText(Html.fromHtml("First Info <b>"+info1+"</b>"+"<br/>Second Info <b>"+info2+"</b>"));
assuming you're using a textview :
myTextView.setText(Html.fromHtml("<h2>"youString"</h2><br><p>"YourSecondString"</p>"));
First define your string in string.xml file which is under values folder in resources folder as:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="select"><b><h2>S</h2></b>elect</string>
</resources>
and then use them as
android:text="#string/select"...
String info1 ="yyy";
String info2 ="mmm";
TextView txt;
txt = (TextView)findViewById(R.id.txt);
txt.setText(Html.fromHtml("<b>" + str1 + "</b>" + "<br />" +
"<small>" + str2 + "</small>" ));
Just pointing out that a SpannableStringBuilder may be an interesting alternative if you're looking for a non-HTML-based solution. This way you could for example also use an inline HTML-styled link (URLSpan) to not execute the default ACTION_VIEW on the provided URL, but have it launch a new activity - or anything else you like.
String boldText = getString(R.string.bold_text);
String italicText = getString(R.string.italic_text);
String strikethroughText = getString(R.string.strikethrough_text);
String urlText = getString(R.string.url_text);
SpannableStringBuilder ssb = new SpannableStringBuilder();
ssb.append(boldText);
ssb.setSpan(new StyleSpan(Typeface.BOLD), ssb.length()-boldText.length(), ssb.length() , Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append(" ");
ssb.append(italicText);
ssb.setSpan(new StyleSpan(Typeface.ITALIC), ssb.length()-italicText.length(), ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append(" ");
ssb.append(strikethroughText);
ssb.setSpan(new StrikethroughSpan(), ssb.length()-strikethroughText.length(), ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append(" ");
ssb.append(urlText);
ssb.setSpan(new URLSpan("http://www.stackoverflow.com"), ssb.length()-urlText.length(), ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView tv = (TextView) findViewById(R.id.spannable_text);
tv.setText(ssb);
Which will look as follows:
Other spans can be found as subclass of CharacterStyle. E.g. the TextAppearanceSpan allows you to do most of the above but then by using xml-declared styles. I've used it to create a Button with two lines of text with different styles (different text size and colour) applied to each line.