53

How to set underline text on textview?

I have used following code but it is not working.

tvHide.setText(Html.fromHtml("<p><u>Hide post</u></p>").toString());
Usama Abdulrehman
  • 1,041
  • 3
  • 11
  • 21
Nirav Modh
  • 757
  • 1
  • 8
  • 18
  • three ways to solve this issue http://stackoverflow.com/questions/2394935/can-i-underline-text-in-an-android-layout/27266015#27266015 – Zar E Ahmer Dec 03 '14 at 07:31
  • 1
    Possible duplicate of [Can I underline text in an android layout?](https://stackoverflow.com/questions/2394935/can-i-underline-text-in-an-android-layout) – Daniel Bickler Nov 14 '17 at 17:21
  • This is not a duplicate of either of those questions because the OP is asking to underline a _textview_, not text itself. Otherwise, his question title needs to be changed. In other words, even if the textview is empty, it should still be underlined.. think of it as a border only on the bottom, but always there. – jungledev Oct 30 '18 at 15:12
  • 2
    [5 Amazing Ways To UnderLine A TextView In Android](https://androidride.com/underline-a-textview-in-android/) – Athira Reddy Nov 26 '19 at 06:45

15 Answers15

103

You have to use SpannableString for that :

String mystring=new String("Hello.....");
SpannableString content = new SpannableString(mystring);
content.setSpan(new UnderlineSpan(), 0, mystring.length(), 0);
yourtextview.setText(content);

Update : You can refer my answer on Underling TextView's here in all possible ways.

Community
  • 1
  • 1
Kartik Domadiya
  • 29,868
  • 19
  • 93
  • 104
  • Just want to add one note here: While setting your span make sure you haven't use textAllCaps = true. It won't work. – Aanal Shah Jun 06 '19 at 14:23
  • avoid giving a plain "0" when it expects flags, in most cases `Spanned.SPAN_EXCLUSIVE_EXCLUSIVE` is the way to go. – Achraf Amil Aug 12 '20 at 08:23
90

Following are the some approaches for underlined text in android:

1st Approach

You can define your string in strings.xml

<string name="your_string"><u>Underlined text</u></string>

And use that string in your xml file

<TextView
            android:id="@+id/txt_underlined"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="@string/your_string"/>

Or you can use that string in your Activity/Fragment

txtView.setText(R.string.your_string);

2nd Approach

To underline the text in TextView, you can use SpannableString

String text="Underlined Text";
SpannableString content = new SpannableString(text);
content.setSpan(new UnderlineSpan(), 0, text.length(), 0);
txtView.setText(content);

3rd Approach

You can make use of setPaintFlags method of TextView to underline the text of TextView.

txtView.setPaintFlags(mTextView.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
txtView.setText("Underlined Text");

4th Approach

Make use of Html.fromHtml(htmlString);

String htmlString="<u>Underlined Text</u>";
txtView.setText(Html.fromHtml(htmlString));

Or

txtView.setText(Html.fromHtml("<u>underlined</u> text"));

Note:

If you have added this line android:textAllCaps="true" in your layout, then none of the above will work. For that, you have to define your string in Caps and then any of the above approach.

akshay
  • 5,811
  • 5
  • 39
  • 58
49

Use this

tvHide.setPaintFlags(tvHide.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
Gowthaman M
  • 8,057
  • 8
  • 35
  • 54
toxa_xa
  • 619
  • 6
  • 8
10

Android supports string formatting using HTML tags in the strings xml. So the following would work:

<string name="label_testinghtmltags"><u>This text has an underscore</u></string>

Then you just use it as you normally would. You can see more in the documentation here

Update:

To further expand on the answer, the documentation says:

... the format(String, Object...) and getString(int, Object...) methods strip all the style information from the string. . The work-around to this is to write the HTML tags with escaped entities, which are then recovered with fromHtml(String), after the formatting takes place

For example, the resulting string from the following code snippet will not show up as containing underscored elements:

<string name="html_bold_test">This <u>%1$s</u> has an underscore</string>
String result = getString(R.string.html_bold_test, "text")

However the result from the following snippet would contain underscores:

<string name="html_bold_test">This &lt;u> %1$s &lt;/u> has an underscore</string>
String result = Html.fromHtml(getString(R.string.html_bold_test, "text"))
Hrafn
  • 2,867
  • 3
  • 25
  • 44
  • @BariqDharmawan I expanded the answer with information from the documentation. Perhaps that could solve your problem. – Hrafn Sep 09 '18 at 13:06
9

Simple and easy way to display underline in TextView is:

yourTextView.getPaint().setUnderlineText(true);

And if you want to remove underlining for that view, you can write below code:

yourTextView.getPaint().setUnderlineText(false);

It will work even though you set android:textAllCaps="true"

Viraj Patel
  • 2,113
  • 16
  • 23
7

Try this,

tv.setPaintFlags(Paint.UNDERLINE_TEXT_FLAG);
Gowthaman M
  • 8,057
  • 8
  • 35
  • 54
Mani
  • 3,394
  • 3
  • 30
  • 36
6

you're almost there: just don't call toString() on Html.fromHtml() and you get a Spanned Object which will do the job ;)

tvHide.setText(Html.fromHtml("<p><u>Hide post</u></p>"));
Brian Mains
  • 50,520
  • 35
  • 148
  • 257
Mobiletainment
  • 22,201
  • 9
  • 82
  • 98
5

Need not to use HTML properties, let's focus on java xD I had the same problem, i found the way to do it in java:

String text="Hide post";
TextView tvHide=(TextView)findViewById(R.id.text);
SpannableString spanString = new SpannableString(text);
spanString.setSpan(new UnderlineSpan(), 0, spanString.length(), 0);
tvHide.setText(spanString );
Shessuky
  • 1,846
  • 21
  • 24
5

Kotlin - normal code

val text = getString(R.string.welcome)

val spannableString = SpannableString(text).apply {
    setSpan(UnderlineSpan(), 0, text.length, 0)
}

text_view.text = spannableString

Kotlin - extension

fun TextView.underline(resource: Int) {
    val text = context.getString(resource)
    val spannableString = SpannableString(text).apply {
        setSpan(UnderlineSpan(), 0, text.length, 0)
    }

    setText(spannableString)
}

usage:

text_view.underline(R.string.welcome)

Kotlin - binding code

@BindingAdapter("underline")
fun underline(view: TextView, resource: Int) {
    if (resource == 0) return

    val text = view.context.getString(resource)
    val spannableString = SpannableString(text).apply {
        setSpan(UnderlineSpan(), 0, text.length, 0)
    }

    view.text = spannableString
}

usage:

<TextView
    android:id="@+id/tv_report_problem"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:underline="@{@string/common_report_problem}" />
Boken
  • 4,825
  • 10
  • 32
  • 42
1

I believe that you need to use CharSequence. You can find an example here.

kgiannakakis
  • 103,016
  • 27
  • 158
  • 194
1

You can do it like:

tvHide.setText(Html.fromHtml("<p><span style='text-decoration: underline'>Hide post</span></p>").toString());

Hope this helps

Mahendra Liya
  • 12,912
  • 14
  • 88
  • 114
1

You can easily add a View with the height of 1dp aligning start and the end of TextView, right below it. You can also use marginTop with negative value to make the underline closer to TextView. If you use your TextView and the under inside a relative layout, it would be much easier for alignments. here is the example:

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<View
  android:id="@+id/viewForgotPasswordUnderline"
  android:layout_width="wrap_content"
  android:layout_height="1dp"
  android:layout_below="@id/txtForgotPassword"
  android:layout_alignStart="@id/txtForgotPassword"
  android:layout_alignEnd="@id/txtForgotPassword"
  android:layout_marginTop="-2dp"
  android:background="@color/lightGray" />

<androidx.appcompat.widget.AppCompatTextView
  android:id="@+id/txtForgotPassword"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerHorizontal="true"
  android:paddingTop="8dp"
  android:text="@string/userLoginForgotPassword"
  android:textColor="@color/lightGray"
  android:textSize="16dp" />
</RelativeLayout>
Mohsen Mousavi
  • 131
  • 2
  • 8
1

Kotlin: do it when you find ID

textview =findViewById<TextView>(R.id.textview).also { it.paint?.isUnderlineText =true }
seekingStillness
  • 4,833
  • 5
  • 38
  • 68
0

In my sign_in.xml file I used this:

<Button
    android:id="@+id/signuptextlinkbtn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:background="@android:color/transparent"
    android:onClick="performSingUpMethod"
    android:text="Sign up now!"
    android:textColor="#5B55FF"
    android:textSize="15dp"
    android:textStyle="bold" />

In my SignIn.java file, I used this:

import android.graphics.Paint;
Button signuptextlinkbutton = (Button) findViewById(R.id.signuptextlinkbtn);
signuptextlinkbutton.setPaintFlags(signuptextlinkbutton.getPaintFlags()| Paint.UNDERLINE_TEXT_FLAG);

Now I can see my link underlined. It was simply text even thought I declared it as a Button.

Jaime Montoya
  • 6,915
  • 14
  • 67
  • 103
0

I use BindingAdapters for things like this.

  1. in a kotlin file you declare a bindingAdapter

    @BindingAdapter("underlineText")
    fun TextView.setUnderlineText(isVisible: Boolean){
         paintFlags = if(isVisible) paintFlags or Paint.UNDERLINE_TEXT_FLAG else paintFlags and Paint.UNDERLINE_TEXT_FLAG.inv()}
    
  1. and then you use it inside your .xml layout

        <TextView
             android:id="@+id/discount_label"
             underlineText="@{true}"
             android:text="underlined text"
             ...
             ...
              />
    
Adamo Branz
  • 164
  • 2
  • 7