How can I display special characters (like –) in the TextView? - android

How can I display special characters(like – ") in a TextView?

You can use the Html.fromHtml() to handle HTML formatted text into a Spannable that TextView can display.

If you know the Unicode value, you can display any UTF-8 character. Example, for " you would have &\#0034;.
See Unicode Characters (at Code Table) for more information.

I've implemented this solution.
Activity class:
textView.setText( getString(R.string.author_quote, "To be or not to be", "Shakespeare") )
strings.xml:
<string name="author_quote">« %1$s » - %2$s</string>
HTML chars are written directly in strings.xml, no additional Html.fromHtml() is needed. It works fine on all my devices.

I've written a custom method that will convert all unicode from hexa to integer and replaces from actual string.
So that text view can read is as a unicode.
have a look ,this will solve your problem...
public String unecodeStr(String escapedString) {
try {
String str;
int from = 0;
int index = escapedString.indexOf("\\u", 0);
while (index > -1) {
str = escapedString.substring(index, index + 6).replace("\\u", "");
try {
Integer iI = Integer.parseInt(str, 16);
char[] chaCha = Character.toChars(iI);
escapedString = escapedString.replaceFirst(str, String.valueOf(chaCha));
} catch (Exception e) {
CustomLog.e("error:", e.getMessage());
}
from = index + 3;
index = escapedString.indexOf("\\u", from);
}
escapedString = escapedString.replace("\\u", "");
} catch (Exception e) {
CustomLog.info("warnning", "emoji parsing error at " + escapedString);
}
return escapedString;
}

Related

How to remove current typeface for some lines only [duplicate]

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>"}}

Android : replacing characters in a string

In my phonebook on my mobile I have all sorts of contacts like :
+(353) 085 123 45 67
00661234567
0871234567
(045)123456
I'm putting them all into E.164 format which I've largely completed but the question I need resolved is this:
How can I strip all characters (including spaces) except numbers in my string, apart from the first character if it is '+' or a number ?
string phoneNumberofContact;
So for example the cases above would look like :
+3530851234567
00661234567
0871234567
045123456
Update
To handle + only in the first position, you could do:
boolean starsWithPlus = input.charAt(0) == '+';
String sanitized = input.replaceAll("[^0-9]", "");
if (startsWithPlus) {
sanitized = "+" + sanitized;
}
So basically I'm checking to see if it starts with plus, then stripping out everything but digits, and then re-adding the plus if it was there.
Original
Assuming you only want to keep + or digits, a simple regex will work, and String provides the replaceAll() method to make it even easier.
String sanitized = input.replaceAll("[^+0-9]", "");
This method would do the trick
public String cleanPhoneDigits(String phonenum) {
StringBuilder builder = new StringBuilder();
if (phonenum.charAt(0).equals('+') {
builder.append('+');
}
for (int i = 1; i < phonenum.length(); i++) {
char c = phonenum.charAt(i);
if (Character.isDigit(c)) {
builder.append(c);
}
}
return builder.toString();
}

How to change First letter of each word to Uppercase in Textview xml

i need to change the text="font roboto regular" to Font Roboto Regular in xml itself, how to do?
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="18sp"
android:textColor="#android:color/black"
android:fontFamily="roboto-regular"
android:text="font roboto regular"
android:inputType="textCapWords"
android:capitalize="words"/>
If someone looking for kotlin way of doing this, then code becomes very simple and beautiful.
yourTextView.text = yourText.split(' ').joinToString(" ") { it.capitalize() }
You can use this code.
String str = "font roboto regular";
String[] strArray = str.split(" ");
StringBuilder builder = new StringBuilder();
for (String s : strArray) {
String cap = s.substring(0, 1).toUpperCase() + s.substring(1);
builder.append(cap + " ");
}
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(builder.toString());
Try this...
Method that convert first letter of each word in a string into an uppercase letter.
private String capitalize(String capString){
StringBuffer capBuffer = new StringBuffer();
Matcher capMatcher = Pattern.compile("([a-z])([a-z]*)", Pattern.CASE_INSENSITIVE).matcher(capString);
while (capMatcher.find()){
capMatcher.appendReplacement(capBuffer, capMatcher.group(1).toUpperCase() + capMatcher.group(2).toLowerCase());
}
return capMatcher.appendTail(capBuffer).toString();
}
Usage:
String chars = capitalize("hello dream world");
//textView.setText(chars);
System.out.println("Output: "+chars);
Result:
Output: Hello Dream World
KOTLIN
val strArrayOBJ = "Your String".split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val builder = StringBuilder()
for (s in strArrayOBJ) {
val cap = s.substring(0, 1).toUpperCase() + s.substring(1)
builder.append("$cap ")
}
txt_OBJ.text=builder.toString()
Modification on the accepted answer to clean out any existing capital letters and prevent the trailing space that the accepted answer leaves behind.
public static String capitalize(#NonNull String input) {
String[] words = input.toLowerCase().split(" ");
StringBuilder builder = new StringBuilder();
for (int i = 0; i < words.length; i++) {
String word = words[i];
if (i > 0 && word.length() > 0) {
builder.append(" ");
}
String cap = word.substring(0, 1).toUpperCase() + word.substring(1);
builder.append(cap);
}
return builder.toString();
}
you can use this method to do it programmatically
public String wordFirstCap(String str)
{
String[] words = str.trim().split(" ");
StringBuilder ret = new StringBuilder();
for(int i = 0; i < words.length; i++)
{
if(words[i].trim().length() > 0)
{
Log.e("words[i].trim",""+words[i].trim().charAt(0));
ret.append(Character.toUpperCase(words[i].trim().charAt(0)));
ret.append(words[i].trim().substring(1));
if(i < words.length - 1) {
ret.append(' ');
}
}
}
return ret.toString();
}
refer this if you want to do it in xml.
You can use
private String capitalize(final String line) {
return Character.toUpperCase(line.charAt(0)) + line.substring(1);
}
refer this How to capitalize the first character of each word in a string
android:capitalize is deprecated.
Follow these steps: https://stackoverflow.com/a/31699306/4409113
Tap icon of ‘Settings’ on the Home screen of your Android Lollipop
Device
At the ‘Settings’ screen, scroll down to the PERSONAL section and
tap the ‘Language & input’ section.
At the ‘Language & input’ section, select your keyboard(which is
marked as current keyboard).
Now tap the ‘Preferences’.
Tap to check the ‘Auto – Capitalization’ to enable it.
And then it should work.
If it didn't, i'd rather to do that in Java.
https://stackoverflow.com/a/1149869/2725203
Have a look at ACL WordUtils.
WordUtils.capitalize("your string") == "Your String"
Another approach is to use StringTokenizer class. The below method works for any number of words in a sentence or in the EditText view. I used this to capitalize the full names field in an app.
public String capWordFirstLetter(String fullname)
{
String fname = "";
String s2;
StringTokenizer tokenizer = new StringTokenizer(fullname);
while (tokenizer.hasMoreTokens())
{
s2 = tokenizer.nextToken().toLowerCase();
if (fname.length() == 0)
fname += s2.substring(0, 1).toUpperCase() + s2.substring(1);
else
fname += " "+s2.substring(0, 1).toUpperCase() + s2.substring(1);
}
return fname;
}
in kotlin, string extension
fun String?.capitalizeText() = (this?.toLowerCase(Locale.getDefault())?.split(" ")?.joinToString(" ") { if (it.length <= 1) it else it.capitalize(Locale.getDefault()) }?.trimEnd())?.trim()
Kotlin extension function for capitalising each word
val String?.capitalizeEachWord
get() = (this?.lowercase(Locale.getDefault())?.split(" ")?.joinToString(" ") {
if (it.length <= 1) it else it.replaceFirstChar { firstChar ->
if (firstChar.isLowerCase()) firstChar.titlecase(
Locale.getDefault()
) else firstChar.toString()
}
}?.trimEnd())?.trim()
As the best way for achieving this used to be the capitalize() fun, but now it got depricated in kotlin. So we have an alternate for this. I've the use case where I'm getting a key from api that'll be customized at front end & will be shown apparently. The value is coming as "RECOMMENDED_OFFERS" which should be updated to be shown as "Recommended Offers".
I've created an extension function :
fun String.updateCapitalizedTextByRemovingUnderscore(specialChar: String): String
that takes a string which need to be replaced with white space (" ") & then customise the words as their 1st character would be in caps. So, the function body looks like :
fun String.updateCapitalizedTextByRemovingUnderscore(
specialChar: String = "") : String {
var tabName = this
// removing the special character coming in parameter & if
exist
if (spclChar.isNotEmpty() && this.contains(specialChar)) {
tabName = this.replace(spclChar, " ")
}
return tabName.lowercase().split(' ').joinToString(" ") {
it.replaceFirstChar { if (it.isLowerCase())
it.titlecase(Locale.getDefault()) else it.toString() } }
}
How to call the extension function :
textView.text =
"RECOMMENDED_OFFERS".updateCapitalizedTextByRemovingUnderscore("_")
OR
textView.text = <api_key>.updateCapitalizedTextByRemovingUnderscore("_")
The desired output will be :
Recommended Offers
Hope this will help.Happy coding :) Cheers!!
capitalize each word
public static String toTitleCase(String string) {
// Check if String is null
if (string == null) {
return null;
}
boolean whiteSpace = true;
StringBuilder builder = new StringBuilder(string); // String builder to store string
final int builderLength = builder.length();
// Loop through builder
for (int i = 0; i < builderLength; ++i) {
char c = builder.charAt(i); // Get character at builders position
if (whiteSpace) {
// Check if character is not white space
if (!Character.isWhitespace(c)) {
// Convert to title case and leave whitespace mode.
builder.setCharAt(i, Character.toTitleCase(c));
whiteSpace = false;
}
} else if (Character.isWhitespace(c)) {
whiteSpace = true; // Set character is white space
} else {
builder.setCharAt(i, Character.toLowerCase(c)); // Set character to lowercase
}
}
return builder.toString(); // Return builders text
}
use String to txt.setText(toTitleCase(stringVal))
don't use android:fontFamily to roboto-regular. hyphen not accept. please rename to roboto_regular.
To capitalize each word in a sentence use the below attribute in xml of that paticular textView.
android:inputType="textCapWords"

Android - Check content of a String

I have a string (length 3-8) assigned to a variable (text). I want to check whether the 2nd and 3rd characters are NOT numeric (a letter or symbol or space..or anything other than numbers).
Elementary way to do this could be:
if(((text.charAt(1)-'0')>=0)&&(text.charAt(1)-'0')<10))||((text.charAt(2)-'0')>=0)&&(text.charAt(2)-'0')<10)))
{
//do nothing, since this means 2nd and/or 3rd characters in the string are numeric
}
else
{
// Your condition is met
}
You could also use REGEX's , if your checking is still more complicated.
Here is Another way to achieve this:
boolean isNumeric = true;
String test = "testing";
char second = test.charAt(1);
char third = test.charAt(2);
try {
Integer.parseInt(String.valueOf(second));
Integer.parseInt(String.valueOf(third));
} catch(NumberFormatException e) {
isNumeric = false;
}
System.out.println("Contains Number in 2nd and 3rd or both position: " + isNumeric);
You might make use of the String.IndexOf(String) method, like:
String digits = "0123456789";
String s2 = text.substring(2,3);
String s3 = text.substring(3,4);
boolean valid = (digits.indexOf(s2) > -1) && (digits.indexOf(s3) > -1);

how to make a specific text on TextView BOLD

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>"}}

Categories

Resources