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
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);
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;
}
});
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;
}
}
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().