Highlight searched text in ListView items

I assume that you have a custom Adapter with getCount() and getView() implemented and already filtering items, and you just need the bold part.

To achieve that, you need to use a SpannableString, which is basically text with markup attached. For example, a TextAppearanceSpan can be used to change typeface, font style, size, and color.

So, you should update your adapter's getView() to change the part where you use textView.setText() into something more or less like this:

String filter = ...;
String itemValue = ...;

int startPos = itemValue.toLowerCase(Locale.US).indexOf(filter.toLowerCase(Locale.US));
int endPos = startPos + filter.length();

if (startPos != -1) // This should always be true, just a sanity check
{
    Spannable spannable = new SpannableString(itemValue);
    ColorStateList blueColor = new ColorStateList(new int[][] { new int[] {}}, new int[] { Color.BLUE });
    TextAppearanceSpan highlightSpan = new TextAppearanceSpan(null, Typeface.BOLD, -1, blueColor, null);

    spannable.setSpan(highlightSpan, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    textView.setText(spannable);
}
else
    textView.setText(itemValue);

Android Search Highlight Example [Case Insensitive Order]

1. Search: [Highlight Specific Word]

public static SpannableStringBuilder highlightSearchText(SpannableStringBuilder fullText, String searchText) {

    if (searchText.length() == 0) return fullText;

    SpannableStringBuilder wordSpan = new SpannableStringBuilder(fullText);
    Pattern p = Pattern.compile(searchText, Pattern.CASE_INSENSITIVE);
    Matcher m = p.matcher(fullText);
    while (m.find()) {

        int wordStart = m.start();
        int wordEnd = m.end();

        setWordSpan(wordSpan, wordStart, wordEnd);

    }

    return wordSpan;
}

2. Search: [Highlight Full Word]

public static SpannableStringBuilder highlightSearchText(SpannableStringBuilder fullText, String searchText) {

    if (searchText.length() == 0) return fullText;

    final String searchBoundary = " \n()।.,;?-+!";
    char[] boundaries = searchBoundary.toCharArray();

    // highlight search text
    if (isNotEquals(searchText, boundaries)) {

        SpannableStringBuilder wordSpan = new SpannableStringBuilder(fullText);
        Pattern p = Pattern.compile(searchText, Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(fullText);
        while (m.find()) {

            int wordStart = m.start();
            while (wordStart >= 0 && isNotEquals(fullText.charAt(wordStart), boundaries)) {
                --wordStart;
            }
            wordStart = wordStart + 1;

            int wordEnd = m.end();
            while (wordEnd < fullText.length() && isNotEquals(fullText.charAt(wordEnd), boundaries)) {
                ++wordEnd;
            }

            setWordSpan(wordSpan, wordStart, wordEnd);

        }

        return wordSpan;

    } else {
        return fullText;
    }
}

private static boolean isNotEquals(String searchText, char[] boundaries) {
    for (char boundary : boundaries) {
        boolean equals = searchText.equals(String.valueOf(boundary));
        if (equals) return false;
    }
    return true;
}

private static boolean isNotEquals(char charAt, char[] boundaries) {
    for (char boundary : boundaries) {
        boolean isEquals = charAt == boundary;
        if (isEquals) return false;
    }
    return true;
}

Common Method:

private static void setWordSpan(SpannableStringBuilder wordSpan, int wordStart, int wordEnd) {
    // Now highlight based on the word boundaries
    ColorStateList redColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{0xffa10901});
    TextAppearanceSpan highlightSpan = new TextAppearanceSpan(null, Typeface.BOLD, -1, redColor, null);

    wordSpan.setSpan(highlightSpan, wordStart, wordEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    wordSpan.setSpan(new BackgroundColorSpan(0xFFFCFF48), wordStart, wordEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    wordSpan.setSpan(new RelativeSizeSpan(1.25f), wordStart, wordEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}