I am trying to filter a RecyclerView
using Android Filterable
class.
I've followed this tutorial Android RecyclerView adding Search Filter to get this task done.
The project runs without errors, I displayed the result array in log and I'm getting correct results but nothing changes in UI
.
Here is my adapter code :
public class CoffretPicturesAdapter extends RecyclerView.Adapter<CoffretPicturesAdapter.MyViewHolder> implements Filterable {
private Context mContext ;
private ArrayList<Picture> mData ;
private ArrayList<Picture> mDataFiltered;
public CoffretPicturesAdapter(Context mContext, ArrayList<Picture> mData) {
this.mContext = mContext;
this.mData = mData;
this.mDataFiltered = mData;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view ;
LayoutInflater mInflater = LayoutInflater.from(mContext);
view = mInflater.inflate(R.layout.cardview_item_coffret,parent,false);
return new MyViewHolder(view);
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
mDataFiltered = mData;
} else {
ArrayList<Picture> filteredList = new ArrayList<>();
for (Picture row : mData) {
// name match condition. this might differ depending on your requirement
// here we are looking for name or phone number match
if (row.getTitle().toLowerCase().contains(charString.toLowerCase())) {
filteredList.add(row);
}
}
mDataFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = mDataFiltered;
return filterResults;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
mDataFiltered = (ArrayList<Picture>) filterResults.values;
notifyDataSetChanged();
}
};
}
@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.coffret_title.setText(mData.get(position).getTitle());
Picasso.with(mContext).load(mData.get(position).getUri()).placeholder(R.drawable.placeholder).resize(500,500).centerCrop().into(holder.coffret_thumbnail);
holder.cardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, "" + mData.get(position).getTitle(), Toast.LENGTH_SHORT).show();
Intent intent = new Intent(mContext, SelectedPicPreviewActivity.class);
intent.putExtra("image_url", mData.get(position).getUri().toString());
mContext.startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return mData.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView coffret_title;
ImageView coffret_thumbnail;
LinearLayout cardView ;
public MyViewHolder(View itemView) {
super(itemView);
coffret_title = (TextView) itemView.findViewById(R.id.coffret_title_id) ;
coffret_thumbnail = (ImageView) itemView.findViewById(R.id.coffret_img_id);
cardView = (LinearLayout) itemView.findViewById(R.id.cardview_id);
}
}
}
Here is the function to get data from my external storage
private ArrayList<Picture> getData() {
ArrayList<Picture> results= new ArrayList<>();
//TARGET FOLDER
File picsFolder = new File(Environment.getExternalStorageDirectory() + "/coffretPics");
Picture s;
if (picsFolder.exists()) {
//GET ALL FILES IN DOWNLOAD FOLDER
File[] files = picsFolder.listFiles();
//LOOP THRU THOSE FILES GETTING NAME AND URI
for (int i = files.length - 1; i >= 0; i--) {
File file = files[i];
s = new Picture();
s.setTitle(file.getName());
s.setUri(Uri.fromFile(file));
results.add(s);
}
}
return results;
}
And this is the function to listen to text input changes
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
// Associate searchable configuration with the SearchView
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.action_search)
.getActionView();
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
searchView.setMaxWidth(Integer.MAX_VALUE);
// listening to search query text change
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// filter recycler view when query submitted
adapter.getFilter().filter(query);
return false;
}
@Override
public boolean onQueryTextChange(String query) {
// filter recycler view when text is changed
adapter.getFilter().filter(query);
return false;
}
});
return true;
}
I hope you guys can help me to solve this problem.
Your recyclerview isn't working with the filtered data.
When you finish filtering and call notifyDataSetChanged();
it actually binds all the visible views with the new content, with onBindViewHolder
method.
You can see that in onBindViewHolder
you are getting the item from mData
when you should get it from mDataFiltered
.