简体   繁体   中英

RecyclerView onClick returns false item

i have a RecyclerView and an EditText, when the search is typed it will filter out the items. but when the search is clicked it just passes the first unfiltered search. here is my code.

here is the FoodAdapter ..

public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.ProductViewHolder> {



    private Context mCtx;
    private static List<FoodModel> productList;

    private OnNoteListener monNoteListener;

    //getting the context and product list with constructor
    public FoodAdapter(Context mCtx, List<FoodModel> productList, OnNoteListener onNoteListener) {
        this.mCtx = mCtx;
        this.productList = productList;
        this.monNoteListener = onNoteListener;
    }

    public void filteredList(List<FoodModel> filteredList) {
        productList = filteredList;
        notifyDataSetChanged();
    }


    @Override
    public ProductViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //inflating and returning our view holder
        LayoutInflater inflater = LayoutInflater.from(mCtx);
        View view = inflater.inflate(R.layout.sam_layout_products, null);
        return new ProductViewHolder(view,monNoteListener);
    }


    @Override
    public void onBindViewHolder(ProductViewHolder holder, int position) {
        //getting the product of the specified position
        FoodModel product = productList.get(position);

        //binding the data with the viewholder views
        holder.txtFoodName.setText(product.getFoodName());
        holder.txtFoodDesc.setText(product.getFoodDesc());
        holder.txtFoodPrice.setText(product.getFoodPrice());
        holder.imageView.setImageDrawable(mCtx.getResources().getDrawable(product.getFoodImage()));
    }


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


    public class ProductViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        TextView txtFoodName, txtFoodDesc, txtFoodPrice;
        ImageView imageView;
        OnNoteListener onNoteListener;

        public ProductViewHolder(View itemView, OnNoteListener onNoteListener) {
            super(itemView);

            txtFoodName = itemView.findViewById(R.id.txtFood);
            txtFoodDesc = itemView.findViewById(R.id.txtFoodDesc);
            txtFoodPrice = itemView.findViewById(R.id.txtFoodPrice);
            imageView = itemView.findViewById(R.id.imageView);
            this.onNoteListener = onNoteListener;

            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            
            onNoteListener.onNoteClick(getAdapterPosition());
        }
    }

    public interface OnNoteListener{
        void onNoteClick(int position);
    }

}

and here is the activity FoodActivity

public class FoodsActivity extends AppCompatActivity implements FoodAdapter.OnNoteListener {
    private DrawerLayout dl;
    private ActionBarDrawerToggle t;
    private NavigationView nv;
    static List<FoodModel> FoodList;
    static List<FoodModel> filteredList;
    //the recyclerview
    RecyclerView recyclerView;
    String NameString;
    FoodAdapter foodAdapter;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.foods_layout);
        setTitle("Foods");


        RecyclerViewFood();


        EditText txtFoodSearch = findViewById(R.id.txtFoodSearch);
        txtFoodSearch.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence query, int i, int i1, int i2) {

            }


            @Override
            public void afterTextChanged(Editable editable) {
                SearchFilter(editable.toString());
            }
        });
    }

    @Override
    public void onNoteClick(int position) {
        Intent intent = new Intent(this, sample_layout.class);
        intent.putExtra("foods", FoodList.get(position));
        startActivity(intent);
    }




    private void SearchFilter(String text){
        recyclerView = (RecyclerView) findViewById(R.id.FoodRecyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        filteredList = new ArrayList<>();
        for(FoodModel item: FoodList){
            if(item.getFoodName().toLowerCase().contains(text.toLowerCase())){
                filteredList.add(item);
            }
        }
        foodAdapter = new FoodAdapter(this,filteredList,this);
        // what can i do to pass the correct item to the next intent
        recyclerView.setAdapter(foodAdapter);
    }



    public void RecyclerViewFood() {
        recyclerView = (RecyclerView) findViewById(R.id.FoodRecyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        FoodList = new ArrayList<>();

        String food_name[] = getResources().getStringArray(R.array.food_name);
        String food_desc[] = getResources().getStringArray(R.array.food_desc);
        String food_price[] = getResources().getStringArray(R.array.food_price);

        int food_image[] = {R.drawable.pic_chickenpizza, R.drawable.pic_dorowot, R.drawable.pic_genfo, R.drawable.pic_kitfo, R.drawable.pic_tibs};

        for (int i = 0, j = 0, k = 0, l = 0; i < food_name.length; i++, j++, k++, l++) {
            FoodList.add(new FoodModel(2, food_name[i], food_desc[j], food_price[k], food_image[l]));
        }

        //creating recyclerview adapter
        foodAdapter= new FoodAdapter(this, FoodList, this);

        //setting adapter to recyclerview
        recyclerView.setAdapter(foodAdapter);
    }

when the search is entered, it works but when the filteredList is clicked its passing the wrong item to the next intent.

First, your adapter implements Filterable .

public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.ProductViewHolder> implements Filterable {

// Filtered list
private List<FoodModel> filterList;
// Normal list
private List<FoodModel> productList;

In your constructor:

this.filterList = productList;
productList = new ArrayList<>(productList);

Implementing Filterable requires overriding the getFilter() method. Filtering the list:

@Override
    public Filter getFilter() {
        return MyFilter;
    }

    private Filter MyFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            List<FoodModel> filteredList = new ArrayList<>();

            if (constraint == null || constraint.length() == 0) {
                filteredList.addAll(productList);
            } else {
                String filterPattern = constraint.toString().trim();

                for (FoodModel item : productList) {
                    if (item.getFoodName().contains(filterPattern)) {
                        filteredList.add(item);
                    }
                }
            }

            FilterResults results = new FilterResults();
            results.values = filteredList;

            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            filterList.clear();
            filterList.addAll((List) results.values);
            notifyDataSetChanged();
        }
    };

This is important that you use the filtered list inside onBindViewHolder:

FoodModel product = filterList.get(position);

Now in your activity:

@Override
      public void afterTextChanged(Editable editable) {
        String newText = editable.toString();
        adapter.getFilter().filter(newText);
  }

Edit: get size of the filtered list instead of normal list:

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

In your adapter's onClick:

startMyActivity ( mCtx , filterList.get(getAdapterPosition() ).getId() );
// method
private void startMyActivity ( Activity activity , long id ) {
Intent intent = new Intent( activity , sample_layout.class);
intent.putExtra("foods", id );
activity.startActivity(intent);
}

This is in continuation for the errors you might be facing in @Prince Ali's code. Make these changes to have context passed to your intent

public class ProductViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    TextView txtFoodName, txtFoodDesc, txtFoodPrice;
    ImageView imageView;
    OnNoteListener onNoteListener;
    View mView; //Add this line
    public ProductViewHolder(View itemView, OnNoteListener onNoteListener) {
            super(itemView);

            txtFoodName = itemView.findViewById(R.id.txtFood);
            txtFoodDesc = itemView.findViewById(R.id.txtFoodDesc);
            txtFoodPrice = itemView.findViewById(R.id.txtFoodPrice);
            imageView = itemView.findViewById(R.id.imageView);
            this.onNoteListener = onNoteListener;

            itemView.setOnClickListener(this);
            mView = itemView; // Add this line
        }

Now in your onClick method

Context mCtx = holder.mView.getContext();
startMyActivity ( mCtx , filterList.get(getAdapterPosition() ).getId() );
// method
private void startMyActivity ( Context context , long id ) {
    Intent intent = new Intent( context , sample_layout.class);
    intent.putExtra("foods", id );
    context.startActivity(intent);
}

Nevermind, i removed the old setOnClickListener and made a new one in the onBindViewHolder with the following code

holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(mCtx, sample_layout.class);
        intent.putExtra("foods", productList.get(position));
        mCtx.startActivity(intent);}

});

and now its working. thank you all for your answers:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM