Lets say I have two textviews, a title, and details, the details is toEndOf the title (same line), and while the title is one line, the details, can be multiple, my question is, how can I configure the details textview that when it starts a new line, instead of aligning it to the previous row of the textview, align it to the title textview, hence creating a paragraph feel.
Please see these screenshot to understand what I'm trying to accomplish (the title is the bold text, details it the rest):
Desired:
What I have so far:
The only solution I can think of is using one textview for both, and format the text with HTML, but what if I need a bigger text size for the title?
Thanks!
You can use SpannableText
This will do the job!
<TextView
..
android:id="#+id/text_view"
/>
...
TextView text=(TextView)findViewById(R.id.text_view);
String head = "Seat (s):";
String body = " The baby name means the meaning of the nam";
setTextWithSpan(text,head+body,head, body,new android.text.style.StyleSpan(android.graphics.Typeface.BOLD));
Custom method
public void setTextWithSpan(TextView textView, String text, String spanTextBold,String secondPartOfText,StyleSpan style) {
SpannableStringBuilder sb = new SpannableStringBuilder(text);
int start = text.indexOf(spanTextBold);
int end = start + spanTextBold.length();
sb.setSpan(style, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
//sb.setSpan(new ForegroundColorSpan(Color.BLUE), start, end ,0); // if you need a color
int startTwo = text.indexOf(secondPartOfText);
int endTwo = startTwo + secondPartOfText.length();
// sb.setSpan(new StyleSpan(Typeface.ITALIC),startTwo,endTwo , 0);
sb.setSpan(new RelativeSizeSpan(0.8f), startTwo, endTwo, 0);
textView.setText(sb);
}
Yes, As you mentioned, I also see One TextView with different strings sizes/colors for texts inside.
To achieve this you need to use SpannableString - Docs link
Also Check this answer for details
Use SpannableText for your issue to separate two textviews.
Related
I have this code
TextView text1 = (TextView) view.findViewById(R.layout.myLayout);
Spanned myBold = (Html.fromHtml("<b>Test<b>", Html.FROM_HTML_MODE_LEGACY));
If I do
text1.setText(myBold);
Then myBold is in bold,which is ok. But when I want to add a string more, like
text1.setText(myBold+"bla");
Then the whole TextView is not bold anymore. Why does the new String "bla" affect this?
Thanks.
Why does the new String "bla" affect this?
Because what you are really doing is:
text1.setText(myBold.toString() + "bla");
A String has no style information. A Spanned object does.
Use TextUtils.concat() instead:
text1.setText(TextUtils.concat(myBold, "bla"));
A better choice would be to use a Bold StyleSpan. In the next sample only the "hello" world will be set to bold by using such technique:
Java:
final SpannableString caption = new SpannableString("hello world");
// Set to bold from index 0 to the length of 'hello'
caption.setSpan(new StyleSpan(Typeface.BOLD), 0, "hello".length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
yourTextView.setText(caption);
Kotlin:
yourTextView.text = SpannableString("hello world").apply {
// Set to bold from index 0 to the length of 'hello'
setSpan(StyleSpan(Typeface.BOLD), 0, "hello".length, Spannable.SPAN_INCLUSIVE_EXCLUSIVE))
}
This would be a more optimal solution rather than using the Html.fromHtml technicque, as it doesn't have to go through the overhead of parsing/interpreting the HTML tags.
In addition, it allows you to combine more styles, sizes, etc, in the same SpannableString.
This is the string which i am getting from web using json api in my code:
String content = "<strong><em>India is the world’s hub for child sex trafficking</em>
</strong></p>\n<p style=\"text-align: center;\"><strong><em>Nearly 40,000 children are
abducted every year… </em></strong></p>\n<p style=\"text-align: center;\"><strong<em>
Every8 minutes a girl child goes missing in India!</em></strong></p>\n<p><strong>Priti
Pathak</strong></p>\n<p>MEET Shivani Shivaji Roy, Senior Inspector, Crime Branch, Mumbai
Police, as she sets out to confront the mastermind behind the child trafficking mafia,"
In this string whatever the text is in
"<strong><em> TEXT </em></strong>"
I want to display it BOLD. So for the above string
<strong><em>India is the world’s hub for child sex trafficking</em></strong>
will be displayed as
India is the world’s hub for child sex trafficking
. This should happen for entire string. This is the code which i am using:
int startIndex = content.indexOf("<strong><em>")+13; // 13 because <strong><em> has 13 characters
String substring = content.substring(startIndex, startIndex+200);
int subendIndex = substring.indexOf("</em></strong>");
int endIndex = startIndex + subendIndex;
SpannableString s = new SpannableString(content);
s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), startIndex, endIndex, 0);
textview.setText(s, BufferType.SPANNABLE );
This code is working but it is setting bold text only to the text whichever is first within strong tag and not to the rest. Because I am setting bold text only to the first tag.
How should i get the startIndex, endIndex of all the "strong tags" and so i can set
s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), startIndex, endIndex, 0);
to all the texts and also the number of times i would have to set the span.
I though of using regex also but i dont know how to get indexes using it. Any help would be nice. Thankyou !
The easier way is to use the Html class:
s = Html.fromHtml(content);
See the documentation for the details.
This is the simple way
TextView TV = (TextView)findViewById(R.id.Tv);
String Title="I N <big>D</big> I A";
TV.setText(Html.fromHtml(Title));
If you want to only bold some strings then I recommend Html.fromHtml. A short sample:
String str = "<b> bold text</b> unbold one";
textView.setText(Html.fromHtml(str));
Here's a list of html tags supported by textview.
Use regular HTML tags in Strings, This text uses bold and italics by using inline tags such as within the string file.. Refer this link Hope this Link would be helpful for you!
I'm using a SpannableString to underline certain words, however, I realized the code I have only highlights the first word if there are multiple words. Not exactly sure how to accomplish highlighting multiple words:
String keyword = "test";
String text = "This is a test to underline the three test words in this test";
SpannableString output = new SpannableString(text);
if (text.indexOf(keyword) > -1)
{
int keywordIndex = text.indexOf(keyword);
int keywordLength = keyword.length();
int start = keywordIndex;
int end = keywordIndex + (keywordLength);
output.setSpan(new UnderlineSpan(), start, end, 0);
}
I was thinking I could split the text at every space and loop through it, but wasn't sure if there was a better way.
I do have this code to highlight multiple words using a regular expression, however, I'm try to avoid regular expressions since it's in an Android app and I'm using it in a ListView and I'm told they are very expensive. Also this code I have only highlight whole words, so using the example text above, if the word "protest" was in the sentence, it wouldn't get highlighted using this code:
Matcher matcher = Pattern.compile("\\b(?:test")\\b").matcher(text);
while (matcher.find())
{
output.setSpan(new UnderlineSpan(), matcher.start(), matcher.end(), 0);
}
A ListView in my application has many string elements like name, experience, date of joining, etc. I just want to make name bold. All the string elements will be in a single TextView.
my XML:
<ImageView
android:id="#+id/logo"
android:layout_width="55dp"
android:layout_height="55dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="15dp" >
</ImageView>
<TextView
android:id="#+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/logo"
android:padding="5dp"
android:textSize="12dp" >
</TextView>
My code to set the TextView of the ListView item:
holder.text.setText(name + "\n" + expirience + " " + dateOfJoininf);
Let's say you have a TextView called etx. You would then use the following code:
final SpannableStringBuilder sb = new SpannableStringBuilder("HELLOO");
final StyleSpan bss = new StyleSpan(android.graphics.Typeface.BOLD); // Span to make text bold
final StyleSpan iss = new StyleSpan(android.graphics.Typeface.ITALIC); //Span to make text italic
sb.setSpan(bss, 0, 4, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold
sb.setSpan(iss, 4, 6, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make last 2 characters Italic
etx.setText(sb);
Based on Imran Rana's answer, here is a generic, reusable method if you need to apply StyleSpans to several TextViews, with support for multiple languages (where indices are variable):
void setTextWithSpan(TextView textView, String text, String spanText, StyleSpan style) {
SpannableStringBuilder sb = new SpannableStringBuilder(text);
int start = text.indexOf(spanText);
int end = start + spanText.length();
sb.setSpan(style, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(sb);
}
Use it in an Activity like so:
#Override
protected void onCreate(Bundle savedInstanceState) {
// ...
StyleSpan boldStyle = new StyleSpan(Typeface.BOLD);
setTextWithSpan((TextView) findViewById(R.id.welcome_text),
getString(R.string.welcome_text),
getString(R.string.welcome_text_bold),
boldStyle);
// ...
}
strings.xml
<string name="welcome_text">Welcome to CompanyName</string>
<string name="welcome_text_bold">CompanyName</string>
Result:
Welcome to CompanyName
You can do it using Kotlin and buildSpannedString extension function from core-ktx
holder.textView.text = buildSpannedString {
bold { append("$name\n") }
append("$experience $dateOfJoining")
}
The answers provided here are correct, but can't be called in a loop because the StyleSpan object is a single contiguous span (not a style that can be applied to multiple spans). Calling setSpan multiple times with the same bold StyleSpan would create one bold span and just move it around in the parent span.
In my case (displaying search results), I needed to make all instances of all the search keywords appear bold. This is what I did:
private static SpannableStringBuilder emboldenKeywords(final String text,
final String[] searchKeywords) {
// searching in the lower case text to make sure we catch all cases
final String loweredMasterText = text.toLowerCase(Locale.ENGLISH);
final SpannableStringBuilder span = new SpannableStringBuilder(text);
// for each keyword
for (final String keyword : searchKeywords) {
// lower the keyword to catch both lower and upper case chars
final String loweredKeyword = keyword.toLowerCase(Locale.ENGLISH);
// start at the beginning of the master text
int offset = 0;
int start;
final int len = keyword.length(); // let's calculate this outside the 'while'
while ((start = loweredMasterText.indexOf(loweredKeyword, offset)) >= 0) {
// make it bold
span.setSpan(new StyleSpan(Typeface.BOLD), start, start+len, SPAN_INCLUSIVE_INCLUSIVE);
// move your offset pointer
offset = start + len;
}
}
// put it in your TextView and smoke it!
return span;
}
Keep in mind that the code above isn't smart enough to skip double-bolding if one keyword is a substring of the other. For example, if you search for "Fish fi" inside "Fishes in the fisty Sea" it will make the "fish" bold once and then the "fi" portion. The good thing is that while inefficient and a bit undesirable, it won't have a visual drawback as your displayed result will still look like
Fishes in the fisty Sea
if you don't know exactly the length of the text before the text portion that you want to make Bold, or even you don't know the length of the text to be Bold, you can easily use HTML tags like the following:
yourTextView.setText(Html.fromHtml("text before " + "<font><b>" + "text to be Bold" + "</b></font>" + " text after"));
<string name="My_Name">Given name is <b>Not Right</b>Please try again </string>
use "b" tag in string.xml file.
also for Italic "i" and Underline "u".
Extending frieder's answer to support case and diacritics insensitivity.
public static String stripDiacritics(String s) {
s = Normalizer.normalize(s, Normalizer.Form.NFD);
s = s.replaceAll("[\\p{InCombiningDiacriticalMarks}]", "");
return s;
}
public static void setTextWithSpan(TextView textView, String text, String spanText, StyleSpan style, boolean caseDiacriticsInsensitive) {
SpannableStringBuilder sb = new SpannableStringBuilder(text);
int start;
if (caseDiacriticsInsensitive) {
start = stripDiacritics(text).toLowerCase(Locale.US).indexOf(stripDiacritics(spanText).toLowerCase(Locale.US));
} else {
start = text.indexOf(spanText);
}
int end = start + spanText.length();
if (start > -1)
sb.setSpan(style, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(sb);
}
If you are using the # srings / your_string annotation, access the strings.xml file and use the <b></b> tag in the part of the text you want.
Example:
<string><b>Bold Text</b><i>italic</i>Normal Text</string>
I recommend to use strings.xml file with CDATA
<string name="mystring"><![CDATA[ <b>Hello</b> <i>World</i> ]]></string>
Then in the java file :
TextView myTextView = (TextView) this.findViewById(R.id.myTextView);
myTextView.setText(Html.fromHtml( getResources().getString(R.string.mystring) ));
To better support translations and remove any dependency on length of the string or particular index, you should use android.text.Annotation in you string defined strings.xml.
In your particular case, you can create a string like below
<string name="bold_name_experience_text"><annotation type="bold">name</annotation> \nexpirience dateOfJoininf</string>
or if you want to substitute these in runtime, you can create a string as follow
<string name="bold_name_experience_text"><annotation type="bold">name</annotation> \n%d %s</string>
You must apply this bold_name_experience_text in your text view label. These annotation class spans get added to your string and then you can iterate on them to apply the bold span.
You can refer to my SO answer which shows the Kotlin code to iterate through these spans and apply the bold span
Remember all the above answers has one of the following flows:
They are using some hard-coded index logic which may crash or give wrong results in some other language
They are using hardcode string in Java code which will result in lots of complicated logic to maintain internalisation
Some used Html.fromHtml which can be acceptable answer depending on the use-case. As Html.fromHtml doesn't always work for all types of HTML attributes for example there is not support of click span. Also depending on OEM you might get different rendered TextView
I have a button in my application. the text in the button goes as "Type: Location" something like that.
I'm wondering whether its possible to change the text on the button as "Type: Location"
i.e Bold the text partially on the button??
Thanks for yoru time in advance.
we have a more better choice like this :android:textStyle="bold"
android api support bold
Simply put your string in strings.xml and change it like this,
<string name="hello"><b>Hello</b> World, fh!</string>
and set this text to your button like this
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="#string/hello"
/>
Sometimes the above approach will not be helpful when you might have to use Dynamic Text. So at that case SpannableString comes into action.
String tempString="Copyright";
Button button=(Button)findViewById(R.id.button);
SpannableString spanString = new SpannableString(tempString);
spanString.setSpan(new StyleSpan(Typeface.BOLD), 0, spanString.length(), 0);
button.setText(spanString);
You can set it using Html.fromHtml() and give as a string, a string resource with HTML elements. Hope this helps!
Using spans:
SpannableStringBuilder builder = new SpannableStringBuilder("Type: your type here!");
StyleSpan boldStyle = new StyleSpan(Typeface.BOLD);
builder.setSpan(boldStyle, 0, 5, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
((Button) findViewById(R.id.button)).setText(builder);
You can use basic markup directory in strings, e.g.
"<b>Type</b>: Location"
See Styling with HTML markup
If want to set text programmatically then use this method
Button
First you have to set button's property in XML
android:textAllCaps="false" // very important without this property might be it won't show effect
public SpannableString setSpanableString(String textString, int start, int end){
SpannableString spanString = new SpannableString(textString);
spanString.setSpan(new StyleSpan(Typeface.BOLD), start, end, 0);
return spanString;
}
Button btn; // get your button reference here
String text = "Hi, Dharmbir";
btn.setText(setSpanableString(text, 4, text.length));// set here your index
TextView
TextView tv; // get your TextView reference here
String text = "Hi, Dharmbir";
tv.setText(setSpanableString(text, 4, text.length));
Output
Hi, Dharmbir