【问题标题】:OnClick for item in RecyclerViewOnClick 在 RecyclerView 中的项目
【发布时间】:2017-12-16 22:36:03
【问题描述】:

我正在目睹RecyclerView 的奇怪行为。所以我在Button 上的ViewHolder 中设置了一个OnClickListener,当用户点击时,这意味着做三件事:

  1. 将当前项目的数据添加到ArrayList[显示在不同的Fragment]

  2. 向用户显示Toast

  3. 修改所选项目的 UI。 [即 Button 的 setVisibility 为 View.INVISIBLE 等..]

现在,虽然OnClickListener 的前两个任务已成功完成并应用于所选项目,但第三个任务旨在修改所选 仅适用于 RecyclerView 上的每个第 9 个项目。

  1. 如何防止这种行为?
  2. 为什么这种行为只发生在第三个任务中?

来自以前的答案。我看到的特定主题,我认为最好将OnClickListener 插入ViewHolder 而不是将其放入onBindViewHolder,这并没有解决问题。我遵循了关于 stackOverflow 的其他建议,但都失败了。

这是我的代码:

static class ItemsRecyclerAdapter extends RecyclerView.Adapter<ItemsRecyclerAdapter.ItemsViewHolder>{

    FragmentActivity fragmentActivity;
    List<ProductItem> data;
    LayoutInflater inflater;
    private int id;
    private int shopCode;

    public ItemsRecyclerAdapter(List<ProductItem> data, FragmentActivity fragmentActivity, int id, int shopCode) {
        this.fragmentActivity = fragmentActivity;
        this.data = data;
        this.inflater = LayoutInflater.from(fragmentActivity);
        this.id = id;
        this.shopCode = shopCode;
    }

    @Override
    public ItemsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = inflater.inflate(R.layout.pricing_item, parent, false);

        return new ItemsViewHolder(v);
    }

    @Override
    public void onBindViewHolder(final ItemsViewHolder holder, int position) {
        ProductItem itemPrice = data.get(position);
        holder.productName.setText(itemPrice.getProductName());
        holder.quantity.setText(itemPrice.getProductQuantity());
        holder.tvPrice.setText(itemPrice.getproductPrice());
        Picasso.with(fragmentActivity).load(itemPrice.getThumbUrl()).into(holder.imgProduct);

    }

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


        class ItemsViewHolder extends RecyclerView.ViewHolder{

        TextView productName, quantity, tvPrice;
        ImageView imgProduct;
        Button btnAddToBasket, btnAdd, btnRemove;

        Typeface myCustomFont = Typeface.createFromAsset(fragmentActivity.getAssets(), "fonts/Assistant-SemiBold.ttf");

        public ItemsViewHolder(View itemView) {
            super(itemView);
            productName = (TextView) itemView.findViewById(R.id.productName);
            quantity = (TextView) itemView.findViewById(R.id.manufacturer);
            tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
            imgProduct = (ImageView) itemView.findViewById(R.id.imgProduct);
            btnAddToBasket = (Button) itemView.findViewById(R.id.btnAddToBasket);
            btnAdd = itemView.findViewById(R.id.btnAdd);
            btnRemove = itemView.findViewById(R.id.btnRemove);

            btnAdd.setVisibility(View.INVISIBLE);
            btnRemove.setVisibility(View.INVISIBLE);

            quantity.setTypeface(myCustomFont);
            productName.setTypeface(myCustomFont);
            tvPrice.setTypeface(myCustomFont);

            Typeface fontAwesomeBasketIcon = Typeface.createFromAsset(fragmentActivity.getAssets(), "fontawesome-webfont.ttf");
            btnAddToBasket.setTypeface(fontAwesomeBasketIcon);
            btnAdd.setTypeface(fontAwesomeBasketIcon);
            btnRemove.setTypeface(fontAwesomeBasketIcon);



            btnAddToBasket.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int pos = getAdapterPosition();

                    MyBasketFragment.myBasketList
                            .add(new ProductItem(data.get(pos).getProductName(), data.get(pos).getProductQuantity(),
                                    data.get(pos).getproductPrice(), data.get(pos).getThumbUrl(), id, shopCode));

                    btnAddToBasket.setOnClickListener(null);


                    Toast.makeText(fragmentActivity, "New product..", Toast.LENGTH_SHORT).show();



                    btnAdd.setVisibility(View.VISIBLE);
                    btnRemove.setVisibility(View.VISIBLE);


                }
            });

            btnAdd.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    ItemsFragment.atomic.incrementAndGet();
                    btnAddToBasket.setText(String.valueOf(atomic.get()));
                }
            });
        }
    }

  }

【问题讨论】:

  • 不幸的是,这就是您应该使用 recyclerview 的原因。 Listview 仅初始化显示的子项,这意味着如果您向下滚动,可以说第六个项目将是第一个项目,因为它是第一个显示项目。所以你应该使用 recyclerview 并向我们询问你奇怪的 recyclerview 问题

标签: android android-recyclerview onclicklistener android-viewholder


【解决方案1】:

在每次单击项目时,我将实例化对象中的布尔值分配为 true,然后运行 ​​notifyDataSetChanged() 其中。使用具有boolean true 的数据对象更新所有项目。这样我可以确保只有选定的对象会被更新。

看起来像这样:

ViewHolder

    class ItemsViewHolder extends RecyclerView.ViewHolder {

        TextView productName, quantity, tvPrice;
        ImageView imgProduct;
        Button btnAddToBasket, btnAdd, btnRemove;

        Typeface myCustomFont = Typeface.createFromAsset(fragmentActivity.getAssets(), "fonts/Assistant-SemiBold.ttf");

        public ItemsViewHolder(View itemView) {
            super(itemView);
            productName = (TextView) itemView.findViewById(R.id.productName);
            quantity = (TextView) itemView.findViewById(R.id.manufacturer);
            tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
            imgProduct = (ImageView) itemView.findViewById(R.id.imgProduct);
            btnAddToBasket = (Button) itemView.findViewById(R.id.btnAddToBasket);
            btnAdd = itemView.findViewById(R.id.btnAdd);
            btnRemove = itemView.findViewById(R.id.btnRemove);

            btnAdd.setVisibility(View.INVISIBLE);
            btnRemove.setVisibility(View.INVISIBLE);

            quantity.setTypeface(myCustomFont);
            productName.setTypeface(myCustomFont);
            tvPrice.setTypeface(myCustomFont);

            Typeface fontAwesomeBasketIcon = Typeface.createFromAsset(fragmentActivity.getAssets(), "fontawesome-webfont.ttf");
            btnAddToBasket.setTypeface(fontAwesomeBasketIcon);
            btnAdd.setTypeface(fontAwesomeBasketIcon);
            btnRemove.setTypeface(fontAwesomeBasketIcon);


        }

        public void bind(final ProductItem item) {
            btnAddToBasket.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    item.clicked = true;
                    item.atomic.incrementAndGet();

                    Toast.makeText(fragmentActivity, "New product..", Toast.LENGTH_SHORT).show();

                    notifyDataSetChanged();

                    MyBasketFragment.myBasketList
                            .add(new ProductItem(item.getProductName(), item.getProductQuantity(),
                                    item.getproductPrice(), item.getThumbUrl(), id, shopCode));
                }
            });

            btnAdd.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    ItemsFragment.atomic.incrementAndGet();
                    btnAddToBasket.setText(String.valueOf(atomic.get()));
                }
            });
        }
    }

onBindViewHolder

 @Override
    public void onBindViewHolder(final ItemsViewHolder holder, final int position) {
        ProductItem itemPrice = data.get(position);
        holder.productName.setText(itemPrice.getProductName());
        holder.quantity.setText(itemPrice.getProductQuantity());
        holder.tvPrice.setText(itemPrice.getproductPrice());
        Picasso.with(fragmentActivity).load(itemPrice.getThumbUrl()).into(holder.imgProduct);

        holder.bind(itemPrice);

        if(itemPrice.clicked){
            holder.btnAddToBasket.setOnClickListener(null);

            holder.btnAddToBasket.setText(String.valueOf(atomic.get()));
            holder.btnAdd.setVisibility(View.VISIBLE);
            holder.btnRemove.setVisibility(View.VISIBLE);

        } else {
            holder.btnAddToBasket.setText("\uf291");
            holder.btnAdd.setVisibility(View.INVISIBLE);
            holder.btnRemove.setVisibility(View.INVISIBLE);
        }
    }

【讨论】:

    【解决方案2】:

    我认为是getAdapterPosition() 造成了问题。请尝试在 viewholder 中创建一个新的 int 属性 positiononBindViewHolder 将位置传递给 viewholder,holder.position = position,并在您的 viewholder 中使用该位置,所以将是 int pos = position 而不是 getAdapterPosition()

    【讨论】:

      猜你喜欢
      • 2016-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-20
      • 1970-01-01
      相关资源
      最近更新 更多