ChatGPT解决这个技术问题 Extra ChatGPT

Can I underline text in an Android layout?

How can I define underlined text in an Android layout xml file?

Here i described best practise with example. see this Answer link

L
Luciano

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"><![CDATA[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);

Hi, i tried the above resource xml code and it diddnt work. it continued to display the underline as a plain text
See also: android.text.Html.fromHtml( ) which returns a Spanned.
You should type it in strings.xml file itself, not doing it by add button. Otherwise you will get this <u> in your strings.xml file and underline in your code
I have come across cases when underlying through <u> tags does not work, e.g. sometimes if you are using a custom font. However, underlying programmatically by UnderlineSpan has yet to fail on me, so I would recommend it as the most reliable solution.
It won't show in editor, but when You start You app - it will be underlined.
G
Guykun

You can try with

textview.setPaintFlags(textview.getPaintFlags() |   Paint.UNDERLINE_TEXT_FLAG);

Maybe a minor point, but OP wanted this defined in XML layout file; otherwise, this is a great solution.
use this solution if you want to clear it
this solution can be used for a Button too
Careful if you use custom fonts or similar, you may need to | Paint.ANTI_ALIAS_FLAG as well or you text will look very sharp. This manifests in lower APIs more often than not.
In Kotlin: textView.paintFlags = textView.paintFlags or Paint.UNDERLINE_TEXT_FLAG
I
Ismail Shaikh

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 &lt;, e.g. result should look like:

<resource>
    <string name="your_string_here">This is an &lt;u&gt;underline&lt;/u&gt;.</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), ...)));

underlined here works perfectly. <u>underline</u> did not work. This is for Android 2.2. Maybe different versions interpret it differently.
@autotravis which one is for 2.2? I did not tested it on older versions and it will be quite unfortunate if different versions handle it differently... Also at least current documentation states that it have to be escaped (link is in the answer).
I've tested underlined on android 2.3 and it works. <u>underline</u> does not work for 2.3. The docs say "Sometimes you may want to create a styled text resource that is also used as a format string. Normally, this won't work because the String.format(String, Object...) method will 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." So I guess you would use the escaping if you run it through that String.format(...) method.
@autotravis yes, you are correct. I use it with String.format(...). I've edited my answer, thank you for your feedback.
On 2.3 and 4.1 (only ones I tried so far) you can just use textView.setText(getText(R.string.text)) instead of having to use getString(), Html.fromHtml() and String.format().
Z
ZooMagic

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

Make sure you edit the string resource file inside the actual XML rather than inside the helper editing UI in Eclipse, at it will escape the
O
Offboard

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);

J
Jemshit Iskenderov

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()

M
Muhammad Reda

To do that in Kotlin:

yourTextView.paint?.isUnderlineText = true


g
gprathour

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.


V
Vishal Yadav

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:

https://i.stack.imgur.com/2XVF8.png


The look and feel of Widget.AppCompat.Button.Borderless.Colored is much better than underlining, however, as @Kiril Vashilo described, you can do it anyway.
For this, this forces the text to be upper case, gives it a large border, and makes it larger than the default text.
j
jk7

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);


J
Justin

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!


While this example works, I quickly realized that if you ever want to have additional control in XML that this just won't do... I have switched to a better solution that involves the following steps: 1) Subclass textview 2) Add support to underline the text via custom attributes to do the underlining as specified above. The only difference is that you only execute the underline code if the custom attribute is set.
V
Volodymyr

The most recent approach of drawing underlined text is described by Romain Guy on medium with available source code on GitHub. This sample application exposes two possible implementations:

A Path-based implementation that requires API level 19

A Region-based implementation that requires API level 1

https://i.stack.imgur.com/42P1r.png


A
Ahsan Ullah Rasel

If you want to achieve this in XML, declare your string in resource and put that resource value into underline tag () of HTML. in TextView, add

android:text="@string/your_text_reference"

And in string resource value,

<string name="your_text_reference"><u>Underline me</u></string>

If you want to achieve this programmatically, for Kotlin use

textView.paintFlags = textView.paintFlags or Paint.UNDERLINE_TEXT_FLAG

or,

textView.text = Html.fromHtml("<p><u>Underline me</u></p>")

A
Aditya

Just use the attribute in string resource file e.g.

<string name="example"><u>Example</u></string>

D
Darush

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>

this is the perfect solution for all view underline with custom color. do not disrespect the transparent background here, for android 4 it is required, your view will have black background w/o it
u
user3786340

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

K
Khemraj Sharma

Most Easy Way

TextView tv = findViewById(R.id.tv);
tv.setText("some text");
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);
            }
        }
    }

If you want

- Clickable underline text?

- Underline multiple parts of TextView?

Then Check This Answer


P
Pragnesh Ghoda シ

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!


D
Darush

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>

h
has19

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

Awesome!! But the color of the underline is gray how to change it to black or any other color?
M
Makalele

Very compact, kotlin version:

tvTitle.apply { 
    text = "foobar"
    paint?.isUnderlineText = true
}

How is this answer any different from this answer posted on April 5?
M
Mark Nashat

try with Class

for java

textview.setPaintFlags(textview.getPaintFlags() |   Paint.UNDERLINE_TEXT_FLAG);

for Kotlin

textview.setPaintFlags(textview.getPaintFlags() or Paint.UNDERLINE_TEXT_FLAG)

h
hqzxzwb

Go to strings.xml resource file Add a string in the resource file with an HTML underline tag where necessary.

strings.xml HTML underline sample

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.


R
Ray Lee

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.


l
lynn8570
HtmlCompat.fromHtml(
                    String.format(context.getString(R.string.set_target_with_underline)),
                    HtmlCompat.FROM_HTML_MODE_LEGACY)
<string name="set_target_with_underline">&lt;u>Set Target&lt;u> </string>

Note the Escape symbol in xml file


a
abby

Its quite late to answer this but suppose if anyone wants to get the text dynamically then they can use this simple one line in their java code which works:

 textView.setText(Html.fromHtml("<p><u>" + get_name + "</u></p>"));

C
Community

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.