TextViewのリンクから下線を削除する-Android


93

2つtextviewを使用してデータベースからのリンクを表示しています。リンクの色を変更できましたが、下線を削除したいと思います

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

XMLまたはコードから実行できますか?

回答:


220

URLSpan下線を付けないバージョンでインスタンスを見つけて置き換えることにより、コードでそれを行うことができます。を呼び出した後、各に以下Linkify.addLinks()の関数を呼び出しstripUnderlines()ます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);
    }

これには、TextPaintの「下線」プロパティを有効にしないURLSpanのカスタマイズバージョンが必要です。

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

9
このソリューションは、スパンのテキストがURLと同じであることを前提としています。これは、基本的なhttp://リンクの場合です。ただし、Linkifyはスマートで、(212)555-1212のような電話番号をURLに変換しますtel:2125551212。この情報を保持するにnew URLSpanNoUnderlineは、呼び出しを渡す必要がspan.getURL()あります。そうしないと、クリックすると例外が発生する不良リンクが生成されます。私は自分で編集権限を持っていないため、この提案されたソリューションをあなたの回答のために編集キューに入れました。
Mike Mueller

8
私のために働いていません。Line SpannableでClass Cast Exceptionを出しますs =(Spannable)textView.getText();
Brijesh Thakur 2013

5
その行をSpannableに置き換えるだけですs = new SpannableString(textView.getText());
FOliveira 2014

1
置き換えるSpannable s = (Spannable) textView.getText()とすると、Spannable s = new SpannableString(textView.getText());私のために動作しません。キャストに戻ると、TextViewにがある場合にのみ機能しますandroid:textIsSelectable=true。なぜだろう?
15年

2
これをandroid:autoLink属性で機能させる方法はありますか?そうでなければ、組み込み機能のために独自のonclickメソッドを作成する必要があるようです。
アルカリン

32

与えられたtextViewとコンテンツ:

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

ハイパーリンクから下線を削除する簡単な方法を次に示します。

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

これは、robUx4によって提案されたアプローチに基づいています。

リンクをクリック可能にするには、次のコードも呼び出す必要があります。

textView.setMovementMethod(LinkMovementMethod.getInstance());

7
リソースから文字列を取得しようとすると、これは機能しないためString content = getResources().getString(R.string.content);、リンクを含む文字列は機能しなくなります。
Rain Man、

1
それはどういうことですか?文字列はそれがどこから来たのか知りません。文字列の内容に違いがある必要があります。
Adriaan Koster

理由はわかりませんがres/values/strings.xml、例とまったく同じものが含まれている文字列を呼び出すと、URLが表示されません。最後にテストできますか?
Rain Man

最後にテストするつもりはありません(-:。文字列の内容を確認したい場合は、両方の文字列をそれぞれのhashCodeと一緒に記録してください。上記のコードをまったく同じ文字列
Adriaan Koster

1
リソースから文字列を取得して機能させるには、エンコードする必要があります。>= &gt;<= &lt;など例えば:<string name="link_to_google" >&lt;a href="https://www.google.com/"&gt;Google&lt;/a&gt;</string>参照developer.android.com/guide/topics/resources/string-resource
Micer

11

UnderlineSpan すでに存在しますが、下線しか設定できません。

別の解決策は、既存の各に下線なしのスパンを追加することURLSpanです。したがって、下線の状態はペイントの直前に無効になります。このようにして、URLSpan(おそらくカスタムの)クラスと他のすべてのスタイルを他の場所に設定しておくことができます。

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

    public NoUnderlineSpan(Parcel src) {}

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

これは、既存のURLSpanオブジェクトを削除せずに設定する方法です。

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

私の意見では、よりエレガントなソリューションを実装しました。カスタムTextViewを作りました。このようにしてTextView、ハイパーリンクを使用するすべてに対して追加のコードを実行する必要はありません。

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

そして、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);
    }
}

3

ここで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
}

使用法:

txtView.removeLinksUnderline()    

2

いつでも、拡張可能なURLの下線削除してみてください。

1> カスタムクラスの作成:

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

これには、TextPaintの「下線」プロパティを有効にしないURLSpanのカスタマイズバージョンが必要です。

2> setSpan with spannable text:

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

ここで、spannableTextは、対象となるSpannableString ... !!!


これが最善の解決策であり、私にとって効果的な唯一の解決策です
GuilhE

このソリューションは、1つのURLを持つテキスト用です。
CoolMind 2018

1

Textview autolinkプロパティを使用していて、下線を削除したい場合は、それを使用できます。

まず、UnderlineSpanを拡張し、下線を削除します。

public class NoUnderlineSpan extends UnderlineSpan {

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

次に、NoUnderlineSpanのインスタンスを作成し、Stringテキストから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);
}

リファレンス:http : //prog3.com/sbdm/blog/maosidiaoxian/article/details/39156563


素晴らしい解決策ですが、電話アプリから戻った後(電話番号をクリックした後)、TextViewに下線が引かれます。
CoolMind 2018

1
はい。アクティビティがバックグラウンドに移動する場合は、onResumeアクティビティ関数でこのコードを使用して、textview no underline状態を維持する必要があります。
Francisco Moya

0

テキストだけが必要で、URLリンクを気にしない場合

これがしますSTRIPリンクが、KEEPテキストを

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

追加のクラスは必要ありません

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

0

これが私の方法です

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

このように呼んでください

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

Appcontrollerは私のアプリケーションクラスで、このメソッドを配置してどこからでもアクセスできるようにします


0

この投稿を見つけたXamarinユーザーの場合、これがどのように機能するかを示します。

  1. 下線の除去を処理するカスタムスパンクラスを作成します。
    class URLSpanNoUnderline : URLSpan {
            public URLSpanNoUnderline (string url) : base (url) {
            }

            public override void UpdateDrawState (TextPaint ds) {
                base.UpdateDrawState (ds);
                ds.UnderlineText = false;
            }
        }
  1. 拡張メソッドを作成してすべてのURLスパンを検索し、カスタムスパンに置き換えます。
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);
            }
        }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.