How to highlight filtered text in RecyclerView when using SearchView widget

后端 未结 4 1433
执念已碎
执念已碎 2020-12-30 16:44

How to highlight search text result in RecyclerView. I found some posts regarding Spannable TextView, but not sure where to implement in my case. Appreciate you can look an

相关标签:
4条回答
  • 2020-12-30 17:12

    As per accepted answer indexOf() is not working in case of string value is "Mumbai" same occurrences inside string. So here I have used "Pattern" and "Matcher" class to make it work. Also, I have added ".toLowerCase()" to make string with same case and query work on string as ignore case. If you no need of ignore case of query string, You can remove .toLowerCase() from this code snippet

      SpannableStringBuilder sb = new SpannableStringBuilder(desc);
            Pattern word = Pattern.compile(query.toLowerCase());
            Matcher match = word.matcher(desc.toLowerCase());
    
            while (match.find()) {
                ForegroundColorSpan fcs = new ForegroundColorSpan(
                        ContextCompat.getColor(context, R.color.colorPrimary)); //specify color here
                    sb.setSpan(fcs, match.start(), match.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
            }
            viewHolders.text_view_title.setText(sb);
    
    0 讨论(0)
  • 2020-12-30 17:18

    Use inside on Bind view holder in Adapter class

    String title1 = Itemlist.get(position).getN_stall_name().toLowerCase(Locale.getDefault());
                holder.title.setText(Itemlist.get(position).getN_stall_name());
    
    if (title1.contains(searchText)) {
                    int startPos = title1.indexOf(searchText);
                    int endPos = startPos + searchText.length();
                    Spannable spanString = Spannable.Factory.getInstance().newSpannable(holder.title.getText());
                    spanString.setSpan(new ForegroundColorSpan(Color.RED), startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    holder.title.setText(spanString);
                }
    

    And now create public method in Adapter class

     public void updateList(List<GetShop> list, String searchText) {
                Itemlist = new ArrayList<>();
                Itemlist.addAll(list);
                this.searchText = searchText;
                notifyDataSetChanged();
            }
    

    Search view listener use inside Activity where you use search view

    SearchView searchview=findviewbyid(R.id.searchview);
        searchview.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                    @Override
                    public boolean onQueryTextSubmit(String query) {
                        return false;
                    }
                    @Override
                    public boolean onQueryTextChange(String newText) {
                        newText = newText.toLowerCase();
                        ArrayList<GetShop> newList = new ArrayList<>();
                        for (GetShop userInfo : items) {
                            String type = userInfo.getN_stall_name().toLowerCase();
                            if (type.contains(newText)) {
                                newList.add(userInfo);
                            }
                        }
                        disp_adapter.updateList(newList, newText);
                        return true;
                    }
                });
    
    0 讨论(0)
  • 2020-12-30 17:19

    change your adapter to

    public class MyRecAdapter extends RecyclerView.Adapter<MyRecAdapter.VH> {
            public List<Post> parkingList;        
            public Context context;
            ArrayList<Post> mCountryModel;  
            String searchText;
    
            public MyRecAdapter(List<Post> parkingList, Context context) {
                this.parkingList = parkingList;
                this.context = context;
            }        
            @Override
            public MyRecAdapter.VH onCreateViewHolder(ViewGroup parent, int viewType) {
                return new MyRecAdapter.VH(LayoutInflater.from(parent.getContext()).inflate(R.layout.mycardview, parent, false));
            }        
            @Override
            public void onBindViewHolder(MyRecAdapter.VH holder, int position) {       
                    String title = parkingList.get(position).getPostTitle();
                    String desc = parkingList.get(position).getPostSubTitle();
    
                    holder.t1.setText(Html.fromHtml(title));                    
                    if(searchText.length()>0){
                        //color your text here
                        int index = desc.indexOf(searchText);
                        while(index>0){
                           SpannableStringBuilder sb = new SpannableStringBuilder(desc);
                           ForegroundColorSpan fcs = new ForegroundColorSpan(Color.rgb(158, 158, 158)); //specify color here
                           sb.setSpan(fcs, index, searchText.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); 
                            index = desc.indexOf(searchText,index+1);
    
                        }
                        holder.t2.setText(sb);  
    
                    }else{
                    holder.t2.setText(Html.fromHtml(desc));  
                    }
    
            }        
            @Override
            public int getItemCount() {
                return parkingList.size();
            }        
            public class VH extends RecyclerView.ViewHolder {
                TextView t1, t2;        
                public VH(View view) {
                    super(view);        
                    t1 = (TextView) view.findViewById(R.id.list_title);
                    t2 = (TextView) view.findViewById(R.id.list_desc);        
                }        
            }          
            public void setFilter(List<Post> countryModels,String searchText) {
                mCountryModel = new ArrayList<>();
                mCountryModel.addAll(countryModels);        
                this.searchText = searchText;
                notifyDataSetChanged();        
            }
    
        }
    

    and set onQueryTextChange to

     @Override
            public boolean onQueryTextChange(String newText) {        
    
                final List<Post> filteredModelList = filter(list, newText);        
                if (filteredModelList.size() > 0) {        
                    myRecAdapter.setFilter(filteredModelList,newText);
                    return true;
                } else {
                    Toast.makeText(Chapter1.this, "Not Found", Toast.LENGTH_SHORT).show();
                    return false;
                }
            }     
    
    0 讨论(0)
  • 2020-12-30 17:23
            while(index>**-1**){
                       SpannableStringBuilder sb = new SpannableStringBuilder(desc);
                       ForegroundColorSpan fcs = new ForegroundColorSpan(Color.rgb(158, 158, 158)); //specify color here
                       sb.setSpan(fcs, index, **index** + searchText.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); 
                        index = desc.indexOf(searchText,index+1);
    
                    }
    

    A little add-on to the previous answer , you should check index >-1 instead, else the first text wont be highlighted. For setSpan , the int end should be your index + searchText.length().

    0 讨论(0)
提交回复
热议问题