Hapus garis bawah dari tautan di TextView - Android

94

Saya menggunakan dua textviewuntuk menampilkan tautan dari database, saya berhasil mengubah warna tautan tetapi saya ingin menghapus garis bawah

email.setText(c.getString(5));
    website.setText(c.getString(6));
    Linkify.addLinks(email, Linkify.ALL);
    Linkify.addLinks(website, Linkify.ALL);

Bisakah saya melakukannya dari XML atau Kode?

Mohamed Ben Dhaou
sumber

Jawaban:

220

Anda dapat melakukannya dalam kode dengan mencari dan mengganti URLSpaninstance dengan versi yang tidak digarisbawahi. Setelah Anda memanggil Linkify.addLinks(), panggil fungsi yang stripUnderlines()ditempel di bawah ini pada masing-masing Anda TextView:

    private void stripUnderlines(TextView textView) {
        Spannable s = new SpannableString(textView.getText());
        URLSpan[] spans = s.getSpans(0, s.length(), URLSpan.class);
        for (URLSpan span: spans) {
            int start = s.getSpanStart(span);
            int end = s.getSpanEnd(span);
            s.removeSpan(span);
            span = new URLSpanNoUnderline(span.getURL());
            s.setSpan(span, start, end, 0);
        }
        textView.setText(s);
    }

Ini memerlukan versi URLSpan yang disesuaikan yang tidak mengaktifkan properti "underline" TextPaint:

    private class URLSpanNoUnderline extends URLSpan {
        public URLSpanNoUnderline(String url) {
            super(url);
        }
        @Override public void updateDrawState(TextPaint ds) {
            super.updateDrawState(ds);
            ds.setUnderlineText(false);
        }
    }
Ruben Scratton
sumber
9
Solusi ini mengasumsikan teks span sama dengan URL, yang merupakan kasus untuk link http: // dasar. Namun, Linkify cerdas dan mengubah nomor telepon seperti (212) 555-1212 menjadi URL tel:2125551212. The new URLSpanNoUnderlinepanggilan harus diteruskan span.getURL()untuk mempertahankan info ini, jika tidak, anda menghasilkan link yang buruk yang menyebabkan pengecualian saat diklik. Saya telah menempatkan solusi yang diusulkan ini dalam antrian edit untuk jawaban Anda, karena saya sendiri tidak memiliki izin edit.
Mike Mueller
8
Tidak Bekerja untuk saya. Ini memberikan Pengecualian Cast Kelas pada Line Spannable s = (Spannable) textView.getText ();
Brijesh Thakur
5
Cukup ganti baris itu dengan Spannable s = new SpannableString (textView.getText ());
FOliveira
1
mengganti dengan Spannable s = (Spannable) textView.getText()dengan Spannable s = new SpannableString(textView.getText());tidak berhasil untuk saya. Jika saya beralih kembali ke casting maka itu berhasil, hanya jika TextView memilikinya android:textIsSelectable=true. Tahu kenapa?
b. Menyala
2
Adakah cara untuk membuat ini berfungsi dengan android:autoLinkatribut? Jika tidak, tampaknya Anda harus membuat metode onclick Anda sendiri untuk fungsionalitas bawaan.
Alkarin
33

Diberikan textView dan konten:

TextView textView = (TextView) findViewById(R.id.your_text_view_id);
String content = "your <a href='http://some.url'>html</a> content";

Berikut adalah cara singkat untuk menghapus garis bawah dari hyperlink:

Spannable s = (Spannable) Html.fromHtml(content);
for (URLSpan u: s.getSpans(0, s.length(), URLSpan.class)) {
    s.setSpan(new UnderlineSpan() {
        public void updateDrawState(TextPaint tp) {
            tp.setUnderlineText(false);
        }
    }, s.getSpanStart(u), s.getSpanEnd(u), 0);
}
textView.setText(s);

Ini didasarkan pada pendekatan yang disarankan oleh robUx4.

Untuk membuat tautan dapat diklik, Anda juga perlu menelepon:

textView.setMovementMethod(LinkMovementMethod.getInstance());
Adriaan Koster
sumber
7
ini tidak berfungsi jika Anda mencoba mendapatkan string dari sumber daya, sehingga String content = getResources().getString(R.string.content);yang menyertakan tautan tidak lagi berfungsi.
Rain Man
1
Bagaimana itu bisa terjadi? String tidak tahu dari mana asalnya. Harus ada perbedaan dalam konten String.
Adriaan Koster
tidak yakin mengapa tetapi tidak menunjukkan url ketika saya memanggil string res/values/strings.xmlyang berisi hal yang persis sama seperti contoh. Bisakah Anda menguji pada akhirnya?
Rain Man
Saya pasti tidak akan menguji di akhir saya (- :. Jika Anda ingin memastikan tentang konten string, catat kedua string bersama dengan kode hash mereka. Saya akan terkejut jika Anda menemukan hasil yang berbeda saat menggunakan kode di atas dengan membalas string yang sama.
Adriaan Koster
1
Jika Anda ingin membuatnya bekerja dengan mendapatkan string dari sumber daya, Anda perlu mengenkodenya. >= &gt;, <= &lt;etc. Misalnya: <string name="link_to_google" >&lt;a href="https://www.google.com/"&gt;Google&lt;/a&gt;</string>Lihat developer.android.com/guide/topics/resources/string-resource
Micer
11

UnderlineSpan sudah ada, tapi hanya bisa menyetel garis bawah.

Solusi lain adalah dengan menambahkan rentang tanpa garis bawah pada setiap yang ada URLSpan. Dengan demikian status garis bawah dinonaktifkan sebelum pengecatan. Dengan cara ini Anda tetap mengatur kelas URLSpan(mungkin khusus) dan semua gaya lainnya di tempat lain.

public class NoUnderlineSpan extends UnderlineSpan {
    public NoUnderlineSpan() {}

    public NoUnderlineSpan(Parcel src) {}

    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setUnderlineText(false);
    }
}

Berikut adalah cara Anda mengaturnya tanpa menghapus objek URLSpan yang ada:

URLSpan[] spans = s.getSpans(0, s.length(), URLSpan.class);
for (URLSpan span: spans) {
    int start = s.getSpanStart(span);
    int end = s.getSpanEnd(span);
    NoUnderlineSpan noUnderline = new NoUnderlineSpan();
    s.setSpan(noUnderline, start, end, 0);
}
robUx4
sumber
3

Saya telah menerapkan solusi yang menurut saya lebih elegan. Saya telah membuat kebiasaanTextView . Dengan cara ini Anda tidak perlu menjalankan kode tambahan untuk setiap TextViewdengan hyperlink.

package com.example.view;

import android.content.Context;
import android.support.v7.widget.AppCompatTextView;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.URLSpan;
import android.util.AttributeSet;

import com.example.utils.UrlSpanNoUnderline;

public class TextViewNoUnderline extends AppCompatTextView {
    public TextViewNoUnderline(Context context) {
        this(context, null);
    }

    public TextViewNoUnderline(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.textViewStyle);
    }

    public TextViewNoUnderline(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setSpannableFactory(Factory.getInstance());
    }

    private static class Factory extends Spannable.Factory {
        private final static Factory sInstance = new Factory();

        public static Factory getInstance() {
            return sInstance;
        }

        @Override
        public Spannable newSpannable(CharSequence source) {
            return new SpannableNoUnderline(source);
        }
    }

    private static class SpannableNoUnderline extends SpannableString {
        public SpannableNoUnderline(CharSequence source) {
            super(source);
        }

        @Override
        public void setSpan(Object what, int start, int end, int flags) {
            if (what instanceof URLSpan) {
                what = new UrlSpanNoUnderline((URLSpan) what);
            }
            super.setSpan(what, start, end, flags);
        }
    }
}

Dan kode untuk UrlSpanNoUnderline:

package com.jankstudios.smmagazine.utils;

import android.text.TextPaint;
import android.text.style.URLSpan;

public class UrlSpanNoUnderline extends URLSpan {
    public UrlSpanNoUnderline(URLSpan src) {
        super(src.getURL());
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        super.updateDrawState(ds);
        ds.setUnderlineText(false);
    }
}
Sam Sunson
sumber
3

Berikut adalah fungsi ekstensi Kotlin :

fun TextView.removeLinksUnderline() {
    val spannable = SpannableString(text)
    for (u in spannable.getSpans(0, spannable.length, URLSpan::class.java)) {
        spannable.setSpan(object : URLSpan(u.url) {
            override fun updateDrawState(ds: TextPaint) {
                super.updateDrawState(ds)
                ds.isUnderlineText = false
            }
        }, spannable.getSpanStart(u), spannable.getSpanEnd(u), 0)
    }
    text = spannable
}

Pemakaian:

txtView.removeLinksUnderline()    
sma6871.dll
sumber
2

Setiap kali, coba hapus garis bawah URL dengan spannable, saya hanya menyarankan hal-hal ini:

1> Membuat kelas Kustom:

private class URLSpanNoUnderline extends URLSpan {
            public URLSpanNoUnderline(String url) {
                super(url);
            }
            @Override public void updateDrawState(TextPaint ds) {
                super.updateDrawState(ds);
                ds.setUnderlineText(false);
            }
        }

Ini memerlukan versi URLSpan yang disesuaikan yang tidak mengaktifkan properti "garis bawah" TextPaint

2> setSpan dengan teks spannable:

spannableText.setSpan(new URLSpanNoUnderline(UrlText), 0, UrlText.length() , 0);

Di sini, spannableText adalah Objek SpannableString ... !!!

Dhruv Raval
sumber
Ini adalah solusi terbaik dan satu-satunya yang berhasil untuk saya
GuilhE
Solusi ini untuk teks dengan satu URL.
CoolMind
1

Jika Anda menggunakan properti tautan otomatis Textview dan ingin menghapus garis bawah, Anda dapat menggunakannya:

Pertama, perpanjang UnderlineSpan dan hapus garis bawah:

public class NoUnderlineSpan extends UnderlineSpan {

    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setUnderlineText(false);
    }
}

Kedua, buat dan contoh NoUnderlineSpan, buat Spannable dari teks String dan atur span ke spannable:

NoUnderlineSpan mNoUnderlineSpan = new NoUnderline();
if (yourTextView.getText() instanceof Spannable) {
    Spannable s = (Spannable) yourTextView.getText();
    s.setSpan(mNoUnderlineSpan, 0, s.length(), Spanned.SPAN_MARK_MARK);
}

Referensi: http://prog3.com/sbdm/blog/maosidiaoxian/article/details/39156563

Francisco Moya
sumber
Solusi bagus, tetapi setelah kembali dari aplikasi Telepon (setelah klik pada nomor telepon) lagi-lagi menggarisbawahi TextView.
CoolMind
1
Ya, jika aktivitas Anda berjalan ke latar belakang, Anda harus menggunakan kode ini di fungsi aktivitas onResume untuk mempertahankan status garis bawah textview tanpa.
Francisco Moya
0

Jika Anda hanya ingin teks dan tidak peduli dengan tautan URL

Ini akan STRIP tautan tetapi TETAP teksnya

private Spannable stripLinks(String content) {
    Spannable s = new SpannableString(content);
    URLSpan[] spans = s.getSpans(0, s.length(), URLSpan.class);
    for (URLSpan span : spans) {
        s.removeSpan(span);
    }

    return s;
}

tidak perlu kelas tambahan

String content = "<a href='http://stackoverflow.com'>Stack Overflow</a> Rocks!";
textView.setText(stripLinks(content));
Samuel
sumber
0

Inilah metode saya

 public static void removeUnderlines(Spannable p_Text) {
            if (p_Text != null && p_Text.toString().length() > 0) {
                URLSpan[] spans = p_Text.getSpans(0, p_Text.length(), URLSpan.class);

                for (URLSpan span : spans) {
                    int start = p_Text.getSpanStart(span);
                    int end = p_Text.getSpanEnd(span);
                    p_Text.removeSpan(span);
                    span = new URLSpanNoUnderline(span.getURL());
                    p_Text.setSpan(span, start, end, 0);
                }
            }
        }

Sebut saja seperti ini

AppController.removeUnderlines((Spannable) eventEmail.getText());

Appcontroller adalah kelas aplikasi saya di mana saya meletakkan metode ini sehingga saya dapat mengaksesnya dari mana saja

Bharat singh
sumber
0

Untuk pengguna Xamarin yang menemukan posting ini, berikut adalah cara saya membuatnya berfungsi:

  1. Buat kelas span kustom untuk menangani pengupasan garis bawah.
    class URLSpanNoUnderline : URLSpan {
            public URLSpanNoUnderline (string url) : base (url) {
            }

            public override void UpdateDrawState (TextPaint ds) {
                base.UpdateDrawState (ds);
                ds.UnderlineText = false;
            }
        }
  1. Buat metode ekstensi untuk menemukan semua span url dan menggantinya dengan span kustom kami.
public static void StripUnderlinesFromLinks (this TextView textView) {
                var spannable = new SpannableStringBuilder (textView.TextFormatted);
                var spans = spannable.GetSpans (0, spannable.Length (), Java.Lang.Class.FromType (typeof (URLSpan)));
                foreach (URLSpan span in spans) {
                    var start = spannable.GetSpanStart (span);
                    var end = spannable.GetSpanEnd (span);
                    spannable.RemoveSpan(span);
                    var newSpan = new URLSpanNoUnderline (span.URL);
                    spannable.SetSpan(newSpan, start, end, 0);
                }
                textView.TextFormatted = spannable;
            }
Justin
sumber
-1
public void setView()
{
TextView t=(TextView) findViewById(R.id.textView3);
        t.setText(Html.fromHtml("<a href=http://www.urdusms.net > UrduSMS "));
        t.setTextColor(Color.BLACK);
        t.setGravity(Gravity.CENTER);
        t.setMovementMethod(LinkMovementMethod.getInstance());

         Spannable s = (Spannable) t.getText();
            URLSpan[] spans = s.getSpans(0, s.length(), URLSpan.class);
            for (URLSpan span: spans) {
                int start = s.getSpanStart(span);
                int end = s.getSpanEnd(span);
                s.removeSpan(span);
                span = new URLSpanline_none(span.getURL());
                s.setSpan(span, start, end, 0);
            }
        t.setText(s);
 }
//inner class is    
private class URLSpanline_none extends URLSpan {
            public URLSpanline_none(String url) {
                super(url);
            }
            @Override public void updateDrawState(TextPaint ds) {
                super.updateDrawState(ds);
                ds.setUnderlineText(false);
            }
        }
sandhu
sumber