Albert Richstein
Albert Richstein

Reputation: 3

RecyclerView clickable objects with filter list

I am relatively new to Android programming. I have a RecycleView with CardView in it settled in rows. On click of any row opens a new Activity associated to that row. Everything was working great until I added the filter functionality to this list. When I search the list and then click on one Item, it doesn't open the activity associated with the filtered results. It opens up an Activity related to the Item at that position in Original list.

Example - Original List : AA, BA, CC, DA, ED, FF

Search : 'A' Filtered results: AA, BA, DA

But when I click on item DA it opens up the Activity for CC. I have called notifyDataSetChanged() on the adapter.

I searched and found similar problems but couldn't implement in my code.

Here is the code:

     public class MainActivity extends AppCompatActivity implements ExampleAdapter.OnItemClickListener{
     public static final String EXTRA_IMG = "imageresource";
     public static final String EXTRA_TXT1 = "text1";
     public static final String EXTRA_TXT2 = "text2";
     public static final String EXTRA_TXT3 = "text3";

     private ArrayList<ExampleItem> mExampleList;
     private RecyclerView mRecyclerView;
     private ExampleAdapter mAdapter;
     private RecyclerView.LayoutManager mLayoutManager;


     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);

         createExampleList();
         buildRecyclerView();

         EditText editText = findViewById(R.id.editText);
         editText.addTextChangedListener(new TextWatcher() {
             @Override
             public void beforeTextChanged(CharSequence s, int start, int count, int after) {

             }

             @Override
             public void onTextChanged(CharSequence s, int start, int before, int count) {

             }

             @Override
             public void afterTextChanged(Editable s) {
                 filter(s.toString());
            }
         });

     }

     private void filter(String text) {
         ArrayList<ExampleItem> filteredList = new ArrayList<>();

         for (ExampleItem item : mExampleList) {
             if (item.getText1().toLowerCase().contains(text.toLowerCase())) {
                 filteredList.add(item);
             }
         }
         mAdapter.filterList(filteredList);
     }

     private void createExampleList() {
        //just creating list
     }

     private void buildRecyclerView() {
         mRecyclerView = findViewById(R.id.recyclerView);
         mRecyclerView.setHasFixedSize(true);
         mLayoutManager = new LinearLayoutManager(this);
         mAdapter = new ExampleAdapter(mExampleList);
         mRecyclerView.setLayoutManager(mLayoutManager);
         mRecyclerView.setAdapter(mAdapter);
         mAdapter.setOnItemClickListener(MainActivity.this);
     }

     @Override
     public void onItemClick(int position) {
         Intent detailintent = new Intent(this,DetailActivity.class);
         ExampleItem clickedItem = mExampleList.get(position);
         detailintent.putExtra(EXTRA_IMG,clickedItem.getImageResource());
         detailintent.putExtra(EXTRA_TXT1,clickedItem.getText1());
         detailintent.putExtra(EXTRA_TXT2,clickedItem.getText2());
         detailintent.putExtra(EXTRA_TXT3,clickedItem.getText3());
         startActivity(detailintent);
     }
     }

     public class ExampleAdapter extends RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder> {
     private ArrayList<ExampleItem> mExampleList;
     private OnItemClickListener mListener;
     public interface OnItemClickListener{
         void onItemClick(int position);
     }
     public void setOnItemClickListener(OnItemClickListener listener){
         mListener=listener;
     }

     public class ExampleViewHolder extends RecyclerView.ViewHolder {
         public ImageView mImageView;
         public TextView mTextView1;
         public TextView mTextView2;
         public TextView mTextView3;

         public ExampleViewHolder(View itemView) {
             super(itemView);
             mImageView = itemView.findViewById(R.id.imageView);
             mTextView1 = itemView.findViewById(R.id.textView);
             mTextView2 = itemView.findViewById(R.id.textView7);
             mTextView3 = itemView.findViewById(R.id.textView2);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(mListener != null ){
                        int position = getAdapterPosition();
                        if(position != RecyclerView.NO_POSITION){
                            mListener.onItemClick(position);
                        }
                    }
                }
            });
         }
     }

     public ExampleAdapter(ArrayList<ExampleItem> exampleList) {
         mExampleList = exampleList;
     }

     @Override
     public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
         View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.example_item,
            parent, false);
         ExampleViewHolder evh = new ExampleViewHolder(v);
         return evh;
     }

     @Override
     public void onBindViewHolder(ExampleViewHolder holder, int position) {
         ExampleItem currentItem = mExampleList.get(position);

         holder.mImageView.setImageResource(currentItem.getImageResource());
         holder.mTextView1.setText(currentItem.getText1());
         holder.mTextView2.setText(currentItem.getText2());
         holder.mTextView3.setText(currentItem.getText3());
}

     @Override
     public int getItemCount() {
         return mExampleList.size();
    }

    public void filterList(ArrayList<ExampleItem> filteredList) {
        mExampleList = filteredList;
        notifyDataSetChanged();
    }
}

Upvotes: 0

Views: 789

Answers (1)

beal
beal

Reputation: 445

You have two lists, one in your activity and one in your adapter.

After filtering your list, you only notify the adapter and only set the adapters mExampleList to the new, filtered list. The Activity's list remains the same.

When you click on an item, you let the activity handle the click event. But the activity still have the old, unfiltered list so it will send the wrong data to your new activity.

Solution: simply add mExampleList = filteredList next to the line mAdapter.filterList(filteredList); in your filtering method

Upvotes: 2

Related Questions