3

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

Sibtain
  • 1,436
  • 21
  • 39
  • You are not setting `spannable` to any view. It's just created, but not used anywhere. – Juanjo Vega Mar 12 '15 at 12:48
  • I tired setting it to a view as well, but the view I got was empty when I printed it. This is what I tried `final ViewHolder holder = new ViewHolder();` `View view = inflater.inflate(R.layout.listview_item, null);` `holder.country = (TextView) view.findViewById(R.id.country);` `holder.country.setText(spannable);` – Sibtain Mar 12 '15 at 13:41
  • Update your answer with your current code and I'll have a look to it. – Juanjo Vega Mar 12 '15 at 16:44
  • Actually I downloaded the code from here http://www.androidbegin.com/tutorial/android-search-listview-using-filter/. I have used the same code. I just don't know how to highlight the searched text. Please help me. Thanks – Sibtain Mar 12 '15 at 19:37
  • http://stackoverflow.com/questions/30206679/searching-custom-listview-with-searched-textcolor-highlighted-in-listview-androi – Quick learner Feb 03 '17 at 09:54

3 Answers3

16

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.

Juanjo Vega
  • 1,410
  • 1
  • 12
  • 20
0

You can do like this..

 public class ListViewAdapter extends BaseAdapter {

    // Declare Variables
    Context mContext;
    LayoutInflater inflater;
    String searchstring="";
    private List<WorldPopulation> worldpopulationlist = null;
    private ArrayList<WorldPopulation> arraylist;

    public ListViewAdapter(Context context, List<WorldPopulation> worldpopulationlist) {
        mContext = context;
        this.worldpopulationlist = worldpopulationlist;
        inflater = LayoutInflater.from(mContext);
        this.arraylist = new ArrayList<WorldPopulation>();
        this.arraylist.addAll(worldpopulationlist);
    }

    public class ViewHolder {
        TextView rank;
    }

    @Override
    public int getCount() {
        return worldpopulationlist.size();
    }

    @Override
    public WorldPopulation getItem(int position) {
        return worldpopulationlist.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public View getView(final int position, View view, ViewGroup parent) {
        final ViewHolder holder;
        if (view == null) {
            holder = new ViewHolder();
            view = inflater.inflate(R.layout.listview_item, null);
            // Locate the TextViews in listview_item.xml
            holder.rank = (TextView) view.findViewById(R.id.ranklabel);

            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }
        // Set the results into TextViews

        String faqsearchstr=worldpopulationlist.get(position).getRank().toLowerCase(Locale.getDefault());

         if (faqsearchstr.contains(searchstring)) {
                Log.e("test", faqsearchstr + " contains: " + searchstring);
                System.out.println("if search text"+faqsearchstr);
                int startPos = faqsearchstr.indexOf(searchstring);
                int endPos = startPos + searchstring.length();

                Spannable spanText = Spannable.Factory.getInstance().newSpannable(worldpopulationlist.get(position).getRank()); // <- EDITED: Use the original string, as `country` has been converted to lowercase.
                spanText.setSpan(new ForegroundColorSpan(Color.GREEN), startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

                holder.rank.setText(spanText, TextView.BufferType.SPANNABLE);
            }
         else 
         {
             System.out.println("else search text"+faqsearchstr);
             holder.rank.setText(worldpopulationlist.get(position).getRank());
         }


        // Listen for ListView Item Click
        view.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // Send single item click data to SingleItemView Class
                Intent intent = new Intent(mContext, QuestionActivity.class);
                // Pass all data rank
            //  intent.putExtra("rank",(worldpopulationlist.get(position).getRank()));
                intent.putExtra("QuestionsIntent",((worldpopulationlist.get(position).getFaqpopulatedData())));

                System.out.println("questionsss.."+(worldpopulationlist.get(position).getFaqpopulatedData()));
                // Start SingleItemView Class
                mContext.startActivity(intent);
            }
        });

        return view;
    }

    // Filter Class
    public void filter(String charText) {
        this.searchstring=charText;
        charText = charText.toLowerCase(Locale.getDefault());
        worldpopulationlist.clear();
        if (charText.length() == 0) {
            System.out.println("inside filter if");
            worldpopulationlist.addAll(arraylist);
        } 
        else 
        {
            for (WorldPopulation wp : arraylist) 
            {
                if (wp.getRank().toLowerCase(Locale.getDefault()).contains(charText)) 
                {
                    System.out.println("inside filter else");
                    worldpopulationlist.add(wp);
                }
            }
        }
        notifyDataSetChanged();
    }
 }
stanleyli
  • 1,427
  • 1
  • 11
  • 28
kapil
  • 1
  • 2
0

Use following code to highlight searched text from search/edit text

input is filtered name and mTextview is your text view which you want to highlight use this method after setting value to text view.

 private void highlightString(String input, TextView mTextView) {
    SpannableString spannableString = new SpannableString(mTextView.getText());
    ForegroundColorSpan[] backgroundSpans = spannableString.getSpans(0, spannableString.length(), ForegroundColorSpan.class);

    for (ForegroundColorSpan span : backgroundSpans) {
        spannableString.removeSpan(span);
    }

    int indexOfKeyword = spannableString.toString().indexOf(input);

    while (indexOfKeyword > 0) {
        spannableString.setSpan(new ForegroundColorSpan(Color.GREEN), indexOfKeyword, indexOfKeyword + input.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

        indexOfKeyword = spannableString.toString().indexOf(input, indexOfKeyword + input.length());
    }

    mTextView.setText(spannableString);
}
Sagar
  • 5,273
  • 4
  • 37
  • 50