Entfernen Sie die Unterstreichung von Links in TextView - Android


92

Ich verwende zwei textview, um Links aus der Datenbank anzuzeigen. Es ist mir gelungen, die Linkfarben zu ändern, aber ich möchte die Unterstreichung entfernen

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

Kann ich das aus XML oder Code machen?

Antworten:


219

Sie können dies im Code tun, indem Sie die URLSpanInstanzen suchen und durch Versionen ersetzen , die nicht unterstreichen. Rufen Sie nach dem Linkify.addLinks()Aufruf die stripUnderlines()unten auf jedem Ihrer TextViews eingefügte Funktion auf :

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

Dies erfordert eine angepasste Version von URLSpan, die die "underline" -Eigenschaft von TextPaint nicht aktiviert:

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

9
Bei dieser Lösung wird davon ausgegangen, dass der Text der Spanne mit der URL übereinstimmt, was bei einem einfachen http: // Link der Fall ist. Linkify ist jedoch intelligent und konvertiert eine Telefonnummer wie (212) 555-1212 in die URL tel:2125551212. Der new URLSpanNoUnderlineAnruf sollte weitergeleitet werden span.getURL(), um diese Informationen beizubehalten. Andernfalls generieren Sie fehlerhafte Links, die beim Klicken Ausnahmen verursachen. Ich habe diese vorgeschlagene Lösung für Ihre Antwort in die Bearbeitungswarteschlange gestellt, da ich selbst keine Bearbeitungsberechtigungen habe.
Mike Mueller

8
Ich arbeite nicht für mich. Es gibt eine Klassenumwandlungsausnahme bei Line Spannable s = (Spannable) textView.getText ();
Brijesh Thakur

5
Ersetzen Sie einfach diese Zeile durch Spannable s = new SpannableString (textView.getText ());
FOliveira

1
Ersetzen durch Spannable s = (Spannable) textView.getText()mit Spannable s = new SpannableString(textView.getText());funktioniert bei mir nicht. Wenn ich wieder zum Casting wechsle, funktioniert es nur, wenn die TextView hat android:textIsSelectable=true. Irgendeine Idee warum?
Clu

2
Gibt es eine Möglichkeit, dies mit dem android:autoLinkAttribut zum Laufen zu bringen? Andernfalls müssen Sie anscheinend Ihre eigenen Onclick-Methoden für die integrierte Funktionalität erstellen.
Alkarin

32

Gegeben eine Textansicht und Inhalt:

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

Hier ist eine übersichtliche Möglichkeit, Unterstreichungen aus Hyperlinks zu entfernen:

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

Dies basiert auf dem von robUx4 vorgeschlagenen Ansatz.

Um die Links anklickbar zu machen, müssen Sie auch anrufen:

textView.setMovementMethod(LinkMovementMethod.getInstance());

7
Dies funktioniert nicht, wenn Sie versuchen, eine Zeichenfolge aus Ressourcen abzurufen, sodass String content = getResources().getString(R.string.content);ein Link nicht mehr funktioniert.
Rain Man

1
Wie kann das sein? Ein String weiß nicht, woher er stammt. Es muss einen Unterschied im String-Inhalt geben.
Adriaan Koster

Ich weiß nicht warum, aber die URL wird nicht angezeigt, wenn ich die Zeichenfolge aufrufe, aus res/values/strings.xmlder genau dasselbe wie im Beispiel enthalten ist. Können Sie am Ende testen?
Rain Man

Ich werde definitiv nicht an meinem Ende testen (-:. Wenn Sie sich über den Inhalt der Zeichenfolge sicher sein möchten, protokollieren Sie beide Zeichenfolgen zusammen mit ihrem Hashcode. Es würde mich überraschen, wenn Sie unterschiedliche Ergebnisse finden, wenn Sie den obigen Code mit dem verwenden genau die gleichen Saiten.
Adriaan Koster

1
Wenn Sie möchten, dass es mit dem Abrufen von Zeichenfolgen aus Ressourcen funktioniert, müssen Sie diese codieren. >= &gt;, <= &lt;usw. Zum Beispiel: <string name="link_to_google" >&lt;a href="https://www.google.com/"&gt;Google&lt;/a&gt;</string>Siehe developer.android.com/guide/topics/resources/string-resource
Micer

11

UnderlineSpan existiert bereits, kann aber nur die Unterstreichung setzen.

Eine andere Lösung besteht darin, jedem vorhandenen Bereich einen Bereich ohne Unterstreichung hinzuzufügen URLSpan. Daher wird der Unterstreichungsstatus unmittelbar vor dem Malen deaktiviert. Auf diese Weise behalten Sie Ihre URLSpan(möglicherweise benutzerdefinierten) Klassen und alle anderen Stile an anderer Stelle bei.

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

    public NoUnderlineSpan(Parcel src) {}

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

So legen Sie es fest, ohne das vorhandene URLSpan-Objekt zu entfernen:

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

3

Ich habe eine Lösung implementiert, die meiner Meinung nach eleganter ist. Ich habe einen Brauch gemachtTextView . Auf diese Weise müssen Sie nicht für jeden Code TextViewmit Hyperlinks zusätzlichen Code ausführen .

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

Und Code für 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);
    }
}

2

Wann immer, versuchen Sie , URL unterstreichen mit spannable zu entfernen, schlage ich nur diese Dinge vor:

1> Benutzerdefinierte Klasse erstellen:

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

Dies erfordert eine angepasste Version von URLSpan, die die "underline" -Eigenschaft von TextPaint nicht aktiviert

2> setSpan mit spannbarem Text:

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

Hier ist spannableText Objekt von SpannableString ... !!!


Dies ist die beste Lösung und die einzige, die für mich funktioniert hat
GuilhE

Diese Lösung ist für einen Text mit einer URL.
CoolMind

2

Hier ist die Kotlin- Erweiterungsfunktion:

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
}

Verwendung:

txtView.removeLinksUnderline()    

1

Wenn Sie die Textview-Autolink-Eigenschaft verwenden und Unterstreichungen entfernen möchten, können Sie sie verwenden:

Erweitern Sie zunächst UnderlineSpan und entfernen Sie die Unterstreichung:

public class NoUnderlineSpan extends UnderlineSpan {

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

Zweitens erstellen Sie eine Instanz von NoUnderlineSpan, erstellen eine Spannable aus dem String-Text und setzen die Spanne auf die 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);
}

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


Gute Lösung, aber nach der Rückkehr von der Telefon-App (nach dem Klicken auf die Telefonnummer) wird TextView erneut unterstrichen.
CoolMind

1
Ja, wenn Ihre Aktivität in den Hintergrund tritt, sollten Sie diesen Code in Ihrer onResume-Aktivitätsfunktion verwenden, um den Status der Textansicht ohne Unterstreichung beizubehalten.
Francisco Moya

0

Wenn Sie nur den Text möchten und sich nicht um den URL-Link kümmern

Dies wird STRIP den Link aber HALTEN den Text

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

Keine zusätzlichen Klassen erforderlich

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

0

Hier ist meine Methode

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

Nennen Sie es so

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

Appcontroller ist meine Anwendungsklasse, in der ich diese Methode verwende, damit ich von überall darauf zugreifen kann


0

Für Xamarin-Benutzer, die diesen Beitrag finden, habe ich Folgendes zum Laufen gebracht:

  1. Erstellen Sie eine benutzerdefinierte Bereichsklasse, um die Unterstreichungen zu entfernen.
    class URLSpanNoUnderline : URLSpan {
            public URLSpanNoUnderline (string url) : base (url) {
            }

            public override void UpdateDrawState (TextPaint ds) {
                base.UpdateDrawState (ds);
                ds.UnderlineText = false;
            }
        }
  1. Erstellen Sie eine Erweiterungsmethode, um alle URL-Bereiche zu finden und durch unsere benutzerdefinierten Bereiche zu ersetzen.
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;
            }

-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);
            }
        }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.