TextView'daki bağlantılardan alt çizgiyi kaldırma - Android


94

textviewVeritabanındaki bağlantıları görüntülemek için iki kullanıyorum , bağlantı renklerini değiştirmeyi başardım ama alt çizgiyi kaldırmak istiyorum

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

Bunu XML'den veya Koddan yapabilir miyim?

Yanıtlar:


220

URLSpanÖrnekleri altını çizmeyen sürümlerle bularak ve değiştirerek kodda yapabilirsiniz. Aramadan sonra , her bir e-postanızın üzerine yapıştırılan Linkify.addLinks()işlevi çağırın :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);
    }

Bu, URLSpan'in TextPaint'in "altı çizili" özelliğini etkinleştirmeyen özelleştirilmiş bir sürümünü gerektirir:

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

9
Bu çözüm, yayılma metninin URL ile aynı olduğunu varsayar, bu da temel bir http: // bağlantısı için geçerlidir. Bununla birlikte, Linkify akıllıdır ve (212) 555-1212 gibi bir telefon numarasını URL'ye dönüştürür tel:2125551212. new URLSpanNoUnderlineÇağrı iletilmesi gereken span.getURL()tıklandığında aksi takdirde neden istisnalar o kadar kötü bağlantılar oluşturmak, bu bilgiyi korumak için. Düzenleme izinlerim olmadığından, bu önerilen çözümü cevabınız için düzenleme kuyruğuna yerleştirdim.
Mike Mueller

8
Benim için çalışmıyor. Satır Spannable s = (Spannable) textView.getText ();
Brijesh Thakur

5
Sadece bu satırı Spannable s = new SpannableString (textView.getText ()) ile değiştirin;
FOliveira

1
ile değiştirerek Spannable s = (Spannable) textView.getText()birlikte Spannable s = new SpannableString(textView.getText());benim için çalışmaz. Yayına geri dönersem, yalnızca TextView varsa çalışır android:textIsSelectable=true. Herhangi bir fikrin neden?
b.lit

2
Bunu android:autoLinköznitelikle çalıştırmanın bir yolu var mı ? Aksi takdirde, yerleşik işlevsellik için kendi onclick yöntemlerinizi oluşturmanız gerekiyor gibi görünüyor.
Alkarin

33

Bir textView ve içerik verildiğinde:

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

Köprülerden alt çizgileri kaldırmanın kısa bir yolu:

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

Bu, robUx4 tarafından önerilen yaklaşıma dayanmaktadır.

Bağlantıları tıklanabilir hale getirmek için ayrıca aramanız gerekir:

textView.setMovementMethod(LinkMovementMethod.getInstance());

7
kaynaklardan bir dize almaya çalışırsanız bu işe yaramaz, dolayısıyla String content = getResources().getString(R.string.content);bir bağlantı içeren artık çalışmaz .
Yağmur Adam

1
Nasıl olabilir? Bir String, nereden geldiğini bilmez. Dize içeriklerinde bir fark olmalıdır.
Adriaan Koster

neden olduğundan emin değilim, ancak res/values/strings.xmlörnekle tam olarak aynı şeyi içeren dizeyi aradığımda url'yi göstermiyor . Sonunda test edebilir misin?
Yağmur Adam

Sonunda kesinlikle test etmeyeceğim (- :. Dize içeriğinden emin olmak istiyorsanız, her iki dizeyi de hashCode ile birlikte günlüğe kaydedin. Yukarıdaki kodu ile birlikte kullanırken farklı sonuçlar bulursanız beni şaşırtabilirim.
Adriaan Koster

1
Kaynaklardan dize alarak çalışmasını sağlamak istiyorsanız, onu kodlamanız gerekir. >= &gt;, <= &lt;Vs Örneğin: <string name="link_to_google" >&lt;a href="https://www.google.com/"&gt;Google&lt;/a&gt;</string>Bkz developer.android.com/guide/topics/resources/string-resource
micer

11

UnderlineSpan zaten var, ancak yalnızca alt çizgiyi ayarlayabilir.

Diğer bir çözüm, mevcut olanların her birine altı çizili olmayan bir aralık eklemektir URLSpan. Böylece alt çizgi durumu boyamadan hemen önce devre dışı bırakılır. Bu şekilde URLSpan(muhtemelen özel) sınıflarınızı ve diğer tüm stilleri başka bir yerde ayarlamış olursunuz .

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

    public NoUnderlineSpan(Parcel src) {}

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

Mevcut URLSpan nesnesini kaldırmadan bunu şu şekilde ayarlayabilirsiniz:

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

Bence daha zarif bir çözüm uyguladım. Bir gelenekTextView yaptım . Bu şekilde her TextViewhiper bağlantı için ekstra kod çalıştırmanıza gerek kalmaz .

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

Ve UrlSpanNoUnderline kodu:

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

İşte Kotlin eklenti işlevi:

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
}

Kullanım:

txtView.removeLinksUnderline()    

2

Her ne zaman, spannable ile URL alt çizgisini kaldırmaya çalışın , yalnızca aşağıdakileri öneririm:

1> Özel sınıf oluşturma:

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

Bu özelleştirilmiş bir sürümünü gerektirir URLSpan TextPaint yönettiği "alt çizgi" özelliğini sağlamaz

2> spannable metin ile setSpan:

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

Burada, spannableText nesne olan SpannableString ... !!!


Bu en iyi çözüm ve benim için işe
yarayan

Bu çözüm, tek URL'li bir metin içindir.
CoolMind

1

Textview autolink özelliğini kullanıyorsanız ve alt çizgileri kaldırmak istiyorsanız, bunu kullanabilirsiniz:

İlk olarak, UnderlineSpan'ı genişletin ve alt çizgiyi kaldırın:

public class NoUnderlineSpan extends UnderlineSpan {

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

İkinci olarak, NoUnderlineSpan örneğini oluşturun ve bir örnek oluşturun, String metninden Spannable oluşturun ve aralığı spannable olarak ayarlayın:

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

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


Güzel çözüm, ancak Telefon uygulamasından döndükten sonra (telefon numarasına tıkladıktan sonra) yine TextView'in altını çiziyor.
CoolMind

1
Evet, etkinliğiniz arka plana giderse, metin görünümü alt çizgi yok durumunu korumak için bu kodu onResume etkinlik işlevinizde kullanmalısınız.
Francisco Moya

0

Sadece metni istiyorsan ve URL bağlantısı hakkında endişelenmiyorsan

Bu bağlantıyı KESECEK , ancak metni SAKLAMAK

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

ek sınıf gerekmez

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

0

İşte benim yöntemim

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

Böyle ara

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

Appcontroller, her yerden erişebilmem için bu yöntemi koyduğum uygulama sınıfım


0

Bu gönderiyi bulan Xamarin kullanıcıları için, onu şu şekilde çalıştırdım:

  1. Alt çizgileri ayırmayı işlemek için özel bir yayılma sınıfı oluşturun.
    class URLSpanNoUnderline : URLSpan {
            public URLSpanNoUnderline (string url) : base (url) {
            }

            public override void UpdateDrawState (TextPaint ds) {
                base.UpdateDrawState (ds);
                ds.UnderlineText = false;
            }
        }
  1. Tüm url aralıklarını bulmak ve bunları özel aralıklarımızla değiştirmek için bir uzantı yöntemi oluşturun.
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);
            }
        }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.