Search code examples
androidlistviewandroid-listviewlistadapter

Highlight searched text in custom adapter listview


I have a listview and want to search text from it. I have done it successfully but now I want to search the item and highlight the searched text in the listview. This is my filter function in the ListViewAdapter:

public void filter(String charText) {

    charText = charText.toLowerCase(Locale.getDefault());
    worldpopulationlist.clear();
    if (charText.length() == 0) {
        worldpopulationlist.addAll(arraylist);
    } 
    else 
    {
        for (WorldPopulation wp : arraylist) 
        {
            // Find charText in wp
            int startPos = wp.getCountry().toLowerCase(
                    Locale.getDefault()).indexOf(charText.toLowerCase(Locale.getDefault()));
            int endPos = startPos + charText.length();
            if (startPos != -1) 
            {
                   Spannable spannable = new SpannableString(wp.getCountry());
                    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);
                   //    countryTextView.setText(spannable);
                    worldpopulationlist.add(wp);

            }

        }
    }
    notifyDataSetChanged();

}

I have googled it and I know that Spannable is used for this purpose but its not working. Please help me and tell me if you need any other related code.

EDIT:

The tutorial I followed was from here. I used the same code with a few minor changes. I just want to highlight the searched text in the list view (just one item e.g. country in this case).


Solution

  • Well, I downloaded the sample project and finally came with the following. Adapt the code to your needs.

    In your filter method, store the string used to perform the filter:

    // Filter Class
    public void filter(String searchString) {
        this.searchString = searchString;
        ...
        // Filtering stuff as normal.
    }
    

    You must declare a member string to store it:

    public class ListViewAdapter extends BaseAdapter {
        ...    
        String searchString = "";
        ...
    

    And, in getView you highlight the search term:

    public View getView(final int position, View view, ViewGroup parent) {
        ...
        // Set the results into TextViews
        WorldPopulation item = worldpopulationlist.get(position);
        holder.rank.setText(item.getRank());
        holder.country.setText(item.getCountry());
        holder.population.setText(item.getPopulation());
    
        // Find charText in wp
        String country = item.getCountry().toLowerCase(Locale.getDefault());
        if (country.contains(searchString)) {
            Log.e("test", country + " contains: " + searchString);
            int startPos = country.indexOf(searchString);
            int endPos = startPos + searchString.length();
    
            Spannable spanText = Spannable.Factory.getInstance().newSpannable(holder.country.getText()); // <- EDITED: Use the original string, as `country` has been converted to lowercase.
            spanText.setSpan(new ForegroundColorSpan(Color.RED), startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    
            holder.country.setText(spanText, TextView.BufferType.SPANNABLE);
        }
        ...
    }
    

    Hope it helps.