Getting wrong item on recyclerview list filtering & selection

走远了吗. 提交于 2019-12-12 02:15:06

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!