Neo Ware Neo Ware - 5 months ago 24
Android Question

Ignore one url in linkify

I have a textview that I currently match for links with:

Linkify.addLinks(holder.tvMessage, Linkify.ALL);


However, now I want to match everything (phonenumbers, emails, urls) except one particulat url, http://dontmatch.com.

I have tried subsequent calls such as:

Linkify.addLinks(holder.tvMessage, Linkify.EMAIL_ADDRESSES);
Linkify.addLinks(holder.tvMessage, Linkify.PHONE_NUMBERS);
Linkify.addLinks(holder.tvMessage, Linkify.MAP_ADDRESSES);
Linkify.addLinks(holder.tvMessage, pattern, "http://");


But it seems that each call overrides the links of the previous just leaving the links of the last call. I am also not sure exactly how to write the regex to match everything but the site I wish to ignore. Do I need a MatchFilter?

Update:

I can filter out the url I don't want with:

Linkify.addLinks(holder.tvMessage, Patterns.WEB_URL, null, new MatchFilter() {
@Override
public boolean acceptMatch(CharSequence seq, int start, int end) {
String url = seq.subSequence(start, end).toString();
//Apply the default matcher too. This will remove any emails that matched.
return !url.contains("dontmatch") && Linkify.sUrlMatchFilter.acceptMatch(seq, start, end);
}
}, null);


But how do I specify that I also want the emails, phone numbers etc?

Answer

In the end I solved it like this, but I really hope there is a better way:

private void linkifyView(TextView textview) {

    Linkify.addLinks(textview, Patterns.WEB_URL, null, new MatchFilter() {
        @Override
        public boolean acceptMatch(CharSequence seq, int start, int end) {
            String url = seq.subSequence(start, end).toString();
            //Apply the default matcher too. This will remove any emails that matched.
            return !url.contains(IGNORE_URL) && Linkify.sUrlMatchFilter.acceptMatch(seq, start, end);
        }
    }, null);

    //Linkify removes any existing spans when you call addLinks, and doesn't provide a way to specify multiple
    //patterns in the call with the MatchFilter. Therefore the only way I can see to add the links for
    //email phone etc is to add them in a separate span, and then merge them into one.
    SpannableString webLinks = new SpannableString(textview.getText());
    SpannableString extraLinks = new SpannableString(textview.getText());

    Linkify.addLinks(extraLinks, Linkify.MAP_ADDRESSES | Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS);

    textview.setText(mergeUrlSpans(webLinks, extraLinks));
}

private SpannableString mergeUrlSpans(SpannableString span1, SpannableString span2) {

    URLSpan[] spans = span2.getSpans(0, span2.length() , URLSpan.class);
    for(URLSpan span : spans) {
        span1.setSpan(span, span2.getSpanStart(span), span2.getSpanEnd(span), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

    return span1;
}