Xóa gạch chân khỏi các liên kết trong TextView - Android


93

Tôi đang sử dụng hai textviewđể hiển thị liên kết từ cơ sở dữ liệu, tôi đã cố gắng thay đổi màu liên kết nhưng tôi muốn xóa gạch dưới

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

Tôi có thể làm điều đó từ XML hoặc Code không?

Câu trả lời:


220

Bạn có thể làm điều đó trong mã bằng cách tìm và thay thế các URLSpanphiên bản bằng phiên bản không gạch dưới. Sau khi bạn gọi Linkify.addLinks(), hãy gọi hàm stripUnderlines()được dán bên dưới trên mỗi TextViews của bạn :

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

Điều này yêu cầu một phiên bản URLSpan tùy chỉnh không kích hoạt thuộc tính "gạch dưới" của TextPaint:

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

9
Giải pháp này giả định văn bản của span giống với URL, đây là trường hợp của một liên kết cơ bản http: //. Tuy nhiên, Linkify rất thông minh và chuyển đổi một số điện thoại như (212) 555-1212 thành URL tel:2125551212. Cuộc new URLSpanNoUnderlinegọi nên được chuyển span.getURL()để giữ lại thông tin này, nếu không bạn tạo ra các liên kết xấu gây ra ngoại lệ khi nhấp vào. Tôi đã đặt giải pháp được đề xuất này trong hàng đợi chỉnh sửa cho câu trả lời của bạn, vì bản thân tôi không có quyền chỉnh sửa.
Mike Mueller,

8
Không làm việc cho tôi. Nó cung cấp cho Class Cast Exception tại Line Spannable s = (Spannable) textView.getText ();
Brijesh Thakur

5
Chỉ cần thay thế dòng đó bằng Spannable s = new SpannableString (textView.getText ());
FOliveira

1
thay thế với Spannable s = (Spannable) textView.getText()với Spannable s = new SpannableString(textView.getText());không làm việc cho tôi. Nếu tôi chuyển trở lại truyền thì nó vẫn hoạt động, chỉ khi TextView có android:textIsSelectable=true. Bất kỳ ý tưởng tại sao?
shoke

2
Có cách nào để làm cho điều này hoạt động với android:autoLinkthuộc tính không? Nếu không, có vẻ như bạn phải tạo các phương thức onclick của riêng mình cho chức năng được tích hợp sẵn.
Alkarin

32

Đưa ra một textView và nội dung:

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

Đây là một cách ngắn gọn để loại bỏ gạch chân khỏi siêu liên kết:

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

Điều này dựa trên phương pháp được đề xuất bởi robUx4.

Để làm cho các liên kết có thể nhấp được, bạn cũng cần gọi:

textView.setMovementMethod(LinkMovementMethod.getInstance());

7
điều này không hoạt động nếu bạn cố gắng lấy một chuỗi từ tài nguyên, do String content = getResources().getString(R.string.content);đó, bao gồm một liên kết không còn hoạt động nữa.
Rain Man

1
Làm thế nào mà có thể được? Một chuỗi không biết nó bắt nguồn từ đâu. Phải có sự khác biệt trong nội dung Chuỗi.
Adriaan Koster

không chắc tại sao nhưng nó không hiển thị url khi tôi gọi chuỗi từ res/values/strings.xmlđó chứa chính xác thứ giống như ví dụ. Bạn có thể kiểm tra cuối cùng của bạn?
Rain Man

Tôi chắc chắn sẽ không kiểm tra ở phần cuối của mình (-:. Nếu bạn muốn chắc chắn về nội dung chuỗi, hãy ghi nhật ký cả hai chuỗi cùng với Mã băm của chúng. Tôi sẽ ngạc nhiên nếu bạn tìm thấy kết quả khác khi sử dụng mã ở trên với các chuỗi giống hệt nhau.
Adriaan Koster

1
Nếu bạn muốn làm cho nó hoạt động với việc lấy chuỗi từ tài nguyên, bạn cần mã hóa nó. >= &gt;, <= &lt;v.v. Ví dụ: <string name="link_to_google" >&lt;a href="https://www.google.com/"&gt;Google&lt;/a&gt;</string>Xem developer.android.com/guide/topics/resources/string-resource
Micer

11

UnderlineSpan đã tồn tại, nhưng chỉ có thể đặt gạch dưới.

Một giải pháp khác là thêm khoảng cách không có gạch chân trên mỗi ô hiện có URLSpan. Do đó, trạng thái gạch chân bị tắt ngay trước khi tô. Bằng cách này, bạn giữ các lớp URLSpan(có thể tùy chỉnh) và tất cả các kiểu khác được đặt ở nơi khác.

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

    public NoUnderlineSpan(Parcel src) {}

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

Đây là cách bạn đặt nó mà không xóa đối tượng URLSpan hiện có:

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

Tôi đã thực hiện một giải pháp, theo ý kiến ​​của tôi, là thanh lịch hơn. Tôi đã thực hiện một tùy chỉnhTextView . Bằng cách này, bạn không cần phải thực thi thêm mã cho mọi TextViewsiêu liên kết.

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

Và mã cho 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

Đây là chức năng mở rộng 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
}

Sử dụng:

txtView.removeLinksUnderline()    

2

Bất cứ khi nào, hãy cố gắng xóa gạch chân URL bằng spannable, tôi chỉ đề xuất những điều sau:

1> Tạo lớp Tùy chỉnh:

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

Điều này yêu cầu phiên bản URLSpan tùy chỉnh không kích hoạt thuộc tính "gạch chân" của TextPaint

2> setSpan với văn bản có thể mở rộng:

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

Ở đây, spannableText là Object của SpannableString ... !!!


Đây là giải pháp tốt nhất và duy nhất mà làm việc cho tôi
GuilhE

Giải pháp này dành cho văn bản có một URL.
CoolMind

1

Nếu bạn đang sử dụng thuộc tính tự động liên kết Textview và bạn muốn xóa gạch dưới, bạn có thể sử dụng nó:

Đầu tiên, hãy mở rộng UnderlineSpan và loại bỏ gạch chân:

public class NoUnderlineSpan extends UnderlineSpan {

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

Thứ hai, tạo và phiên bản của NoUnderlineSpan, tạo Spannable từ văn bản String và đặt span là 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);
}

Tham khảo: http://prog3.com/sbdm/blog/maosidiaoxian/article/details/39156563


Giải pháp tốt, nhưng sau khi quay lại từ ứng dụng Điện thoại (sau khi nhấp vào số điện thoại), nó lại nhấn mạnh TextView.
CoolMind

1
Có, nếu hoạt động của bạn ở chế độ nền, bạn nên sử dụng mã này trong chức năng hoạt động onResume của mình để duy trì trạng thái textview không có gạch dưới.
Francisco Moya

0

Nếu bạn chỉ muốn văn bản và không bận tâm về liên kết URL

Thao tác này sẽ ĐĂNG liên kết nhưng GIỮ văn bản

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

không yêu cầu các lớp học bổ sung

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

0

Đây là phương pháp của tôi

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

Gọi nó như thế này

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

Appcontroller là lớp ứng dụng của tôi, nơi tôi đặt phương thức này để tôi có thể truy cập nó từ mọi nơi


0

Đối với những người dùng Xamarin tìm thấy bài đăng này, đây là cách tôi làm cho nó hoạt động:

  1. Tạo một lớp span tùy chỉnh để xử lý việc loại bỏ các gạch dưới.
    class URLSpanNoUnderline : URLSpan {
            public URLSpanNoUnderline (string url) : base (url) {
            }

            public override void UpdateDrawState (TextPaint ds) {
                base.UpdateDrawState (ds);
                ds.UnderlineText = false;
            }
        }
  1. Tạo một phương thức mở rộng để tìm tất cả các nhịp url và thay thế chúng bằng các nhịp tùy chỉnh của chúng tôi.
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);
            }
        }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.