Search code examples
javaandroidregexword-boundary

Regex-based linkifying not working as expected


I need to highlight the result of a searched hashtag in an Android app. Say my search term is "#fun".

Sample string: "#fun #funny #fun123 #funtimes #fun#hi"

Desired output: "#fun #funny #fun123 #funtimes #fun#hi"

I tried the following -

Pattern.compile(searchTerm + "\\b");

where searchTerm is "#fun".

Result: "#fun #funny #fun123 #funtimes #fun#hi"

Shouldn't the word boundary stop the substring highlight in strings like "#funny"?

This is how I'm applying the regex:

private void addLinkToSpan(Spannable s, Link link) {
        Pattern pattern = Pattern.compile(searchTerm + "\\b");
        Matcher matcher = pattern.matcher(mText);

        while (matcher.find()) {

            int start = matcher.start();

            if (start >= 0) {
                int end = start + link.getText().length();

                applyLink(link, new ClickableLinkSpan.Range(start, end), s);
            }
        }
    }

private void applyLink(final Link link, final ClickableLinkSpan.Range range, Spannable text) {
        ClickableLinkSpan linkSpan = new ClickableLinkSpan(link, range);
        text.setSpan(linkSpan, range.start, range.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

        StyleSpan styleSpan = new StyleSpan(link.getTextStyle().ordinal());
        text.setSpan(styleSpan, range.start, range.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

Solution

  • You need to pass the matcher.start() and matcher.end() to the ClickableLinkSpan.Range method:

    while (matcher.find()) { 
        applyLink(link, new ClickableLinkSpan.Range(matcher.start(), matcher.end()), s); 
    }
    

    The matcher.start() contains the exact index of the match value start position in the input string, and the matcher.end() holds the end index of the current match.