So, I have a RecyclerView that uses "swipe to dismiss" and implements filterable.
What works: The swipe to dismiss and filterable work individually as expected. I can swipe to dismiss with the proper animation (I also delete a row from my SQLite db upon this action). I can also filter the cards using the native filterable.
What doesn't work: When I swipe to dismiss after filtering, the position is incorrect and as expected then, the corresponding incorrect row is deleted from my db.
What I think: I believe I need to somehow update my Activity arrayList after/during the filter process.
my search code in Activity
//create options menu
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_jar_options, menu);
/*return super.onCreateOptionsMenu(menu);*/
action_search = menu.findItem(R.id.menu_jar_action_search);
SearchView searchView = (SearchView) action_search.getActionView();
searchView.setBackgroundColor(0xffffffff);
search(searchView);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
//search
private void search(SearchView searchView) {
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText.toLowerCase());
return true;
}
});
}
my swipe code in Activity (cleaned up for clarity purposes)
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction){
if (direction ==ItemTouchHelper.RIGHT){
//swipe right - delete card
final int position = viewHolder.getAdapterPosition();
//get necessary data from item
s_deleteIdentifier = arrayList.get(position).getIdentifier();
s_deleteIdentifier = (!FormatHelper.isStringEmpty(s_deleteIdentifier)) ? s_deleteIdentifier : "";
s_deleteName = arrayList.get(position).getName();
s_deleteName = (!FormatHelper.isStringEmpty(s_deleteName)) ? s_deleteName : "";
//REMOVE ME after testing
Toast.makeText(JarActivity.this, "" +position +" " +s_deleteName, Toast.LENGTH_SHORT).show();
adapter.notifyItemRemoved(position);
arrayList.remove(position);
//user confirms delete, so delete row from db
DatabaseHelper.getInstance(JarActivity.this).deleteRow(
"table",
"IDENTIFIER = ?",
new String[] {s_deleteIdentifier}
);
}
my filter code in adapter
@Override
public Filter getFilter(){
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence){
String charString;
if (charSequence != null) charString = charSequence.toString();
else charString = "";
if (charString.isEmpty()){
arrayListFiltered = arrayList;
}else{
ArrayList<JarObject> filteredList = new ArrayList<>();
for (JarObject jarObject : arrayList) {
if (jarObject.getName().toLowerCase().contains(charString) ||
jarObject.getLocation().toLowerCase().contains(charString) ||
jarObject.getUserNote().toLowerCase().contains(charString) ||
jarObject.getSummary().toLowerCase().contains(charString)
)
filteredList.add(jarObject);
}
arrayListFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = arrayListFiltered;
return filterResults;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
arrayListFiltered = (ArrayList<JarObject>) filterResults.values;
notifyDataSetChanged();
}
};
}
The items in your original list and the filtered list won't be in the same positions. I don't have the ability to throw together an example right now but you should be able to override the adapters getItemId()
method to return something meaningful and use the ViewHolder.getItemId()
to get the actual item you want to delete instead of depending on the position.
You could also expose your filtered list so you can access it from your activity to get the item from the filtered list based off the position, then search your original list to get the proper position.