TextView의 링크에서 밑줄 제거-Android


94

두 개 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의 "underline"속성을 활성화하지 않는 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
이 솔루션은 범위의 텍스트가 기본 http : // 링크의 경우 인 URL과 동일하다고 가정합니다. 그러나 Linkify는 스마트하며 (212) 555-1212와 같은 전화 번호를 URL로 변환합니다 tel:2125551212. new URLSpanNoUnderline호출이 전달되어야 span.getURL()클릭하면, 그렇지 않으면 당신은 원인 예외 나쁜 링크를 생성,이 정보를 유지. 직접 편집 권한이 없기 때문에이 제안 된 솔루션을 귀하의 답변에 대한 편집 대기열에 배치했습니다.
Mike Mueller 2011 년

8
나를 위해 일하지 않습니다. Line Spannable에서 Class Cast 예외를 제공합니다. s = (Spannable) textView.getText ();
Brijesh Thakur

5
해당 줄을 Spannable s = new SpannableString (textView.getText ());
FOliveira

1
함께 교체 Spannable s = (Spannable) textView.getText()로하는 것은 Spannable s = new SpannableString(textView.getText());나를 위해 작동하지 않습니다. 캐스팅으로 다시 전환하면 TextView에 android:textIsSelectable=true. 왜 그런지 아세요?
b.lit 17:37에

2
android:autoLink속성 으로이 작업을 수행 할 수있는 방법이 있습니까? 그렇지 않으면 내장 기능에 대한 고유 한 onclick 메소드를 만들어야하는 것 같습니다.
Alkarin

33

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 2015 년

이유는 모르겠지만 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

때마다 spannable로 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의 "underline"속성을 활성화하지 않는 URLSpan 의 사용자 정의 버전이 필요합니다.

2> 스팬 가능한 텍스트가있는 setSpan :

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

여기서, spannableText은 의 객체입니다 SpannableString은 ...!


이것은 최선의 솔루션과 나를 위해 일한 유일한 것입니다
GuilhE

이 솔루션은 URL이 하나 인 텍스트 용입니다.
CoolMind

1

Textview 자동 링크 속성을 사용하고 있고 밑줄을 제거하려면 다음을 사용할 수 있습니다.

먼저 UnderlineSpan을 확장하고 밑줄을 제거합니다.

public class NoUnderlineSpan extends UnderlineSpan {

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

둘째, NoUnderlineSpan을 만들고 인스턴스화하고, String 텍스트에서 Spannable을 만들고 범위를 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

1
예, 활동이 백그라운드로 이동하는 경우 onResume 활동 함수에서이 코드를 사용하여 textview no underline 상태를 유지해야합니다.
Francisco Moya 2018

0

텍스트 만 원하고 URL 링크는 신경 쓰지 않는 경우

이 것 스트립 링크를하지만 보관 텍스트를

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.