Search code examples
androidlistviewtexthighlightandroid-cursoradapter

How to change background color of searched text in listview-cursoradapter while typing in searchview?


I've seen tutorials about highlighting text in listview using Spannable string but there is none about searching text from database and highlighting in listview.

I have a listview which gets data from database/cursor and shows with the help of cursoradapter. I've placed searchview in action bar to search text from database table.

Now i want that when i type a character or word in searchview, every matched result from database table should highlight/change background color of textview in listview.

I'm confuse about where to perform search operation(in activity or cursoradapter) and how to display result ?

This code is in activity and i can get result from db with like query.

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.search_menu, menu);

    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView = (SearchView) menu.findItem(R.id.action_search)
            .getActionView();
    searchView.setSearchableInfo(searchManager
            .getSearchableInfo(getComponentName()));
    searchView.setOnQueryTextListener(this);
    return true;
}

@Override
public boolean onQueryTextChange(String text) {

    searchText(text + "*");
    return false;
}

@Override
public boolean onQueryTextSubmit(String text) {

    searchText(text + "*");
    return false;
}

private void searchText(String text) {

    if (text != null) {

        localDB.openDB();
        Cursor cursor = localDB.searchDBText(text);
        if (cursor != null && cursor.moveToFirst()) {

            String message = cursor.getString(cursor
                    .getColumnIndex(LocalStoreDB.ROW_MESSAGE));

            Log.i("searchText message:", message);
        } else {

            Log.i("searchText message:", "cursor is null");
        }
        cursor.close();
        localDB.closeDB();
    } else {

        Log.i("searchText message:", "input text is null");
    }
}

Solution

  • Apologize for answering after a while, but still it would help someone in need.

    What i end up doing is pass the text to a method in adapter, then find the text in bindView() with Pattern-Matcher and highlight the text with SpannableString

    Following is the code in adapter:

    public class AdapterSingleChat extends CursorAdapter {
    
        private static int indexThumb;
    
        //String to search and highlight
        String textToSearch = null;
    
        public AdapterSingleChat(Context context, Cursor cursor, int flags) {
            super(context, cursor, flags);
    
            //caching the column index
            indexThumb = cursor.getColumnIndex(SQLiteStoreDB.ROW_TEXT);
       }
    
       //ViewHolder()...
    
       //newView()....
    
       @Override
       public void bindView(View view, Context context, Cursor cursor){
    
            //Text from cursor in which search will perform
            String cursorText = cursor.getString(indexText);
    
            //Spannable string to highlight matching searched words
            SpannableString spannableStringSearch = null;
    
            if ((textToSearch != null) && (!textToSearch.isEmpty())) {
    
    
                spannableStringSearch = new SpannableString(cursorText);
    
                //compile the pattern of input text
                Pattern pattern = Pattern.compile(textToSearch,
                        Pattern.CASE_INSENSITIVE);
    
                //giving the compliled pattern to matcher to find matching pattern in cursor text
                Matcher matcher = pattern.matcher(cursorText);
                spannableStringSearch.setSpan(new BackgroundColorSpan(
                            Color.TRANSPARENT), 0, spannableStringSearch.length(),
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                while (matcher.find()) {
    
                    //highlight all matching words in cursor with white background(since i have a colorfull background image)
                    spannableStringSearch.setSpan(new BackgroundColorSpan(
                                Color.WHITE), matcher.start(), matcher.end(),
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
            }
    
            if(spannableStringSearch != null{
    
                //if search has performed set spannable string in textview
                holder.tvCursorText.setText(spannableStringSearch);
            }else{
    
                //else set plain cursor text
                holder.tvCursorText.setText(cursorText);
            }
       }
    
       //Pass the text from activity(from  SearchManager, EditText or any other input type) here
       private void searchText(String text) {
    
           this.textToSearch = text;
       }
    

    and yes, do not forget to swapCursor() or notifyDataSetChanged() after inputting words.