Can I underline text in an Android layout?
-
25-09-2019 - |
Question
How can I define underlined text in an Android layout xml
file?
Solution
It can be achieved if you are using a string resource xml file, which supports HTML tags like <b></b>
, <i></i>
and <u></u>
.
<resources>
<string name="your_string_here">This is an <u>underline</u>.</string>
</resources>
If you want to underline something from code use:
TextView textView = (TextView) view.findViewById(R.id.textview);
SpannableString content = new SpannableString("Content");
content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
textView.setText(content);
OTHER TIPS
You can try with
textview.setPaintFlags(textview.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
The "accepted" answer above does NOT work (when you try to use the string like textView.setText(Html.fromHtml(String.format(getString(...), ...)))
.
As stated in the documentations you must escape (html entity encoded) opening bracket of the inner tags with <
, e.g. result should look like:
<resource>
<string name="your_string_here">This is an <u>underline</u>.</string>
</resources>
Then in your code you can set the text with:
TextView textView = (TextView) view.findViewById(R.id.textview);
textView.setText(Html.fromHtml(String.format(getString(R.string.my_string), ...)));
Strings.xml file content:
<resource>
<string name="my_text">This is an <u>underline</u>.</string>
</resources>
Layout xml file shold use the above string resource with below properties of textview, as shown below:
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/my_text"
android:selectAllOnFocus="false"
android:linksClickable="false"
android:autoLink="all"
/>
For Button and TextView this is the easiest way:
Button:
Button button = (Button) findViewById(R.id.btton1);
button.setPaintFlags(button.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
Textview:
TextView textView = (TextView) findViewById(R.id.textview1);
textView.setPaintFlags(textView.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
One line solution
myTextView.setText(Html.fromHtml("<p><u>I am Underlined text</u></p>"));
It is bit late but could be useful for someone.
In Kotlin extension function can be used. This can only be used from code, not xml.
fun TextView.underline() {
paintFlags = paintFlags or Paint.UNDERLINE_TEXT_FLAG
}
Usage:
tv_change_number.underline()
tv_resend_otp.underline()
I know this is a late answer, but I came up with a solution that works pretty well... I took the answer from Anthony Forloney for underlining text in code and created a subclass of TextView that handles that for you. Then you can just use the subclass in XML whenever you want to have an underlined TextView.
Here is the class I created:
import android.content.Context;
import android.text.Editable;
import android.text.SpannableString;
import android.text.TextWatcher;
import android.text.style.UnderlineSpan;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* Created with IntelliJ IDEA.
* User: Justin
* Date: 9/11/13
* Time: 1:10 AM
*/
public class UnderlineTextView extends TextView
{
private boolean m_modifyingText = false;
public UnderlineTextView(Context context)
{
super(context);
init();
}
public UnderlineTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
public UnderlineTextView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
private void init()
{
addTextChangedListener(new TextWatcher()
{
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
//Do nothing here... we don't care
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
//Do nothing here... we don't care
}
@Override
public void afterTextChanged(Editable s)
{
if (m_modifyingText)
return;
underlineText();
}
});
underlineText();
}
private void underlineText()
{
if (m_modifyingText)
return;
m_modifyingText = true;
SpannableString content = new SpannableString(getText());
content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
setText(content);
m_modifyingText = false;
}
}
Now... whenever you want to create an underlined textview in XML, you just do the following:
<com.your.package.name.UnderlineTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:text="This text is underlined"
android:textColor="@color/blue_light"
android:textSize="12sp"
android:textStyle="italic"/>
I have added additional options in this XML snippet to show that my example works with changing the text color, size, and style...
Hope this helps!
check out the underscored clickable button style:
<TextView
android:id="@+id/btn_some_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn_add_contact"
android:textAllCaps="false"
android:textColor="#57a0d4"
style="@style/Widget.AppCompat.Button.Borderless.Colored" />
strings.xml:
<string name="btn_add_contact"><u>Add new contact</u></string>
Result:
A cleaner way instead of the
textView.setPaintFlags(textView.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
method is to use
textView.getPaint().setUnderlineText(true);
And if you need to later turn off underlining for that view, such as in a reused view in a RecyclerView, textView.getPaint().setUnderlineText(false);
Just use the attribute in string resource file e.g.
<string name="example"><u>Example</u></string>
I used this xml drawable to create a bottom-border and applied the drawable as the background to my textview
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle" >
<solid android:color="@android:color/transparent" />
</shape>
</item>
<item android:top="-5dp" android:right="-5dp" android:left="-5dp">
<shape>
<solid android:color="@android:color/transparent" />
<stroke
android:width="1.5dp"
android:color="@color/pure_white" />
</shape>
</item>
</layer-list>
A simple and flexible solution in xml:
<View
android:layout_width="match_parent"
android:layout_height="3sp"
android:layout_alignLeft="@+id/your_text_view_need_underline"
android:layout_alignRight="@+id/your_text_view_need_underline"
android:layout_below="@+id/your_text_view_need_underline"
android:background="@color/your_color" />
Damn, it is most simple to use
TextView tv = findViewById(R.id.tv);
tv.setText("some text");
Underline whole TextView
setUnderLineText(tv, tv.getText().toString());
Underline some part of TextView
setUnderLineText(tv, "some");
Also support TextView childs like EditText, Button, Checkbox
public void setUnderLineText(TextView tv, String textToUnderLine) {
String tvt = tv.getText().toString();
int ofe = tvt.indexOf(textToUnderLine, 0);
UnderlineSpan underlineSpan = new UnderlineSpan();
SpannableString wordToSpan = new SpannableString(tv.getText());
for (int ofs = 0; ofs < tvt.length() && ofe != -1; ofs = ofe + 1) {
ofe = tvt.indexOf(textToUnderLine, ofs);
if (ofe == -1)
break;
else {
wordToSpan.setSpan(underlineSpan, ofe, ofe + textToUnderLine.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(wordToSpan, TextView.BufferType.SPANNABLE);
}
}
}
check my answer here to make clickable underline text or underline multiple parts of TextView
another solution is to a create a custom view that extend TextView as shown below
public class UnderLineTextView extends TextView {
public UnderLineTextView(Context context) {
super(context);
this.setPaintFlags(Paint.UNDERLINE_TEXT_FLAG);
}
public UnderLineTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.setPaintFlags(Paint.UNDERLINE_TEXT_FLAG);
}
}
and just add to xml as shown below
<yourpackage.UnderLineTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="underline text"
/>
try this code
in XML
<resource>
<string name="my_text"><![CDATA[This is an <u>underline</u>]]></string>
</resources>
in Code
TextView textView = (TextView) view.findViewById(R.id.textview);
textView.setText(Html.fromHtml(getString(R.string.my_text)));
Good Luck!
I simplified Samuel's answer:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!--https://stackoverflow.com/a/40706098/4726718-->
<item
android:left="-5dp"
android:right="-5dp"
android:top="-5dp">
<shape>
<stroke
android:width="1.5dp"
android:color="@color/colorAccent" />
</shape>
</item>
</layer-list>
- Go to strings.xml resource file
- Add a string in the resource file with an HTML underline tag where necessary.
- Call the string resource ID in your Java code as following:
sampleTextView.setText(R.string.sample_string);
- The output should have the word "Stackoverflow" underlined.
Furthermore, the following code will not print the underline:
String sampleString = getString(R.string.sample_string);
sampleTextView.setText(sampleString);
Instead, use the following code to retain rich text format:
CharSequence sampleString = getText(R.string.sample_string);
sampleTextView.setText(sampleString);
"You can use either getString(int) or getText(int) to retrieve a string. getText(int) retains any rich text styling applied to the string." Android documentation.
Refer to the documentation: https://developer.android.com/guide/topics/resources/string-resource.html
I hope this helps.
The top voted answer is right and simplest. However, sometimes you may find that not working for some font, but working for others.(Which problem I just came across when dealing with Chinese.)
Solution is do not use "WRAP_CONTENT" only for your TextView, cause there is no extra space for drawing the line. You may set fixed height to your TextView, or use android:paddingVertical with WRAP_CONTENT.
HtmlCompat.fromHtml(
String.format(context.getString(R.string.set_target_with_underline)),
HtmlCompat.FROM_HTML_MODE_LEGACY)
<string name="set_target_with_underline"><u>Set Target<u> </string>
Note the Escape symbol in xml file
I had a problem where I'm using a custom font and the underline created with the resource file trick (<u>Underlined text</u>
) did work but Android managed to transform the underline to a sort of strike trough.
I used this answer to draw a border below the textview myself: https://stackoverflow.com/a/10732993/664449. Obviously this doesn't work for partial underlined text or multilined text.