问题
I have an edittext on top & below is list in recyclerview. I first use edittext to filter list & then on selecting specific item from list just print/toast on app.
My problem is, I am able to filter list however, when I select specific item from list, it shows wrong item name means get from original list instead of filtered.
Below is my part code inside fragment
onCreateView() {
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(context,
new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
// TODO Handle item click
// Send the event to the host activity
Intent intent = new Intent();
intent.putExtra("Name", nameList.get(position).getName());
getTargetFragment().onActivityResult(
getTargetRequestCode(), 101, intent);
dismiss();
}
})
);
addTextListener();
}
public void addTextListener(){
editTextSearch.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence query, int start, int before, int count) {
adapter.getFilter().filter(query.toString().toLowerCase());
}
});
}
My adapter class code
public class NameListAdapter extends RecyclerView.Adapter<NameListAdapter.DataObjectHolder>
implements Filterable {
private ArrayList<NameDetail> originalNameDetailArrayList;
private List<NameDetail> filterNameDetailList;
private Context mContext = null;
private ValueFilter valueFilter;
@Override
public NameListAdapter.DataObjectHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.sd_custom_cardview_for_name_list_item, parent, false);
DataObjectHolder dataObjectHolder = new DataObjectHolder(view);
return dataObjectHolder;
}
@Override
public Filter getFilter() {
if (valueFilter == null) {
valueFilter = new ValueFilter();
}
return valueFilter;
}
public class DataObjectHolder extends RecyclerView.ViewHolder {
TextView textViewName;
ImageView image;
public DataObjectHolder(View itemView) {
super(itemView);
mContext = itemView.getContext();
textViewName = (TextView)itemView.findViewById(R.id.textView_Name);
}
}
public NameListAdapter(Context context, ArrayList<NameDetail> originalNameDetailArrayList) {
this.mContext = context;
this.originalNameDetailArrayList = originalNameDetailArrayList;
this.filterNameDetailList = originalNameDetailArrayList;
}
@Override
public void onBindViewHolder(final NameListAdapter.DataObjectHolder holder, int position) {
holder.textViewName.setText(originalNameDetailArrayList.get(position).getName());
}
@Override
public int getItemCount() {
return originalNameDetailArrayList.size();
}
private class ValueFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<NameDetail> filterList = new ArrayList<NameDetail>();
for (int i = 0; i < filterNameDetailList.size(); i++) {
if ((filterNameDetailList.get(i).getName().toUpperCase())
.contains(constraint.toString().toUpperCase())) {
NameDetail listItem = new RegionDetail();
listItem.setID(filterNameDetailList.get(i).getID());
listItem.setName(filterNameDetailList.get(i).getName());
filterList.add(listItem);
}
}
results.count = filterList.size();
results.values = filterList;
} else {
results.count = filterNameDetailList.size();
results.values = filterNameDetailList;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
originalNameDetailArrayList = (ArrayList<NameDetail>) results.values;
notifyDataSetChanged();
Log.v("Size", " : " + originalNameDetailArrayList.size());
if (originalNameDetailArrayList.size() == 0) {
new GlobalToast().showToastMessage(mContext, mContext.getResources().getString(R.string.no_records_found));
}
}
}
}
回答1:
I know this is late but i was having the same problem. Since i solved mine, i figured to help you with your.
It is easy fix. Create a method inside your recycler view adapter that returns your model like below.
public Model getItem (int position) {
return modelList.get(position)
}
here modelList
is List
or ArrayList
of Model
.
then call this method on your filtered list as recyclerAdapter.getItem(position)
I hope this helps. This is my first time answering on stack Overflow, reply if it helps you.
回答2:
I think the problem is intent.putExtra("Name", nameList.get(position).getName());
here you get the item of the original list. But you want the item of the filtered list which is inside your adapter.
I'd recomment using an onclicklistener inside your adapter:
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// your implementation
}
});
Or create a function in your adapter getFilteredItem(position)
.
Edit
Another idea is create a callback in your fragment and pass it through the adapter. Call this callback in the onclick inside your adapter:
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callback.onItemClicked(item);
}
});
Then you can call inside your fragment:
public void onItemClicked(MyItem item) {
// your implementation
item.getName(); // do whatever you want with the name
}
回答3:
I think the problem is here :
@Override
public Filter getFilter() {
if (valueFilter == null) {
valueFilter = new ValueFilter();
}
return valueFilter;
}
You are filtering on onTextChanged
, but you are reusing the old filter instead of creating a new one. On every getFilter request you need to create a new filter like this:
@Override
public Filter getFilter() {
return new ValueFilter()
}
Hope this works for you.
来源:https://stackoverflow.com/questions/41634533/getting-wrong-item-on-recyclerview-list-filtering-selection