【问题标题】:How to fix Checkbox in RecyclerView when no solution works?没有解决方案时如何修复 RecyclerView 中的复选框?
【发布时间】:2019-09-13 20:54:30
【问题描述】:

我正在尝试在我的回收站视图中设置一个复选框,但我面临着不受我控制的随机检查的常见问题。我检查了一个项目,同时正在检查更多随机项目。

我意识到这是一个常见问题,但我在这里找到的解决方案似乎不起作用。在许多其他人中,我试图遵循此线程中的不同说明: Android RecyclerView checkbox checks itself 但问题似乎是函数 isSelected 和 setSelected 无法解析。

我最好的猜测是,造成这种复杂性的原因可能是我的 onCheckedChange 操作实际上是与主活动接口的,正如您在下面的代码底部看到的那样。这是使代码复杂化的原因吗(无法避免)?

  public LocationRecyclerViewAdapter(List<IndividualLocation> styles,
                                     Context context, ClickListener cardClickListener, OnCheckedChangeListener checkedChangeListener, int selectedTheme) {
    this.context = context;
    this.listOfLocations = styles;
    this.selectedTheme = selectedTheme;
    this.clickListener = cardClickListener;
    this.onCheckedChangeListener = checkedChangeListener;

  }


  @Override
  public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    int singleRvCardToUse = R.layout.single_location_map_view_rv_card;
    View itemView = LayoutInflater.from(parent.getContext()).inflate(singleRvCardToUse, parent, false);
    return new ViewHolder(itemView);
  }

  public interface ClickListener {
    void onItemClick(int position);
  }

  public interface OnCheckedChangeListener {
    void onCheckboxClick(int position);
  }

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

  @Override
  public void onBindViewHolder(final ViewHolder card, int position) {

    final IndividualLocation locationCard = listOfLocations.get(position);

    card.nameTextView.setText(locationCard.getName());
    card.addressTextView.setText(locationCard.getAddress());
    card.hoursTextView.setText(locationCard.getHours());
    card.priceTextView.setText(locationCard.getPrice());
    card.categoryTextView.setText(locationCard.getCategory());
    card.cuisineTextView.setText(locationCard.getCuisine());
    card.happyHourTextView.setText(locationCard.getHappyHour());
    card.lunchDealTextView.setText(locationCard.getLunchDeal());
    card.websiteTextView.setText("WEBSITE");
    card.newPlaceTextView.setText(locationCard.getNewPlace());

    card.websiteTextView.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        String url = locationCard.getWebsite();
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(url));
        context.startActivity(intent);
      }
    });


  static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    TextView nameTextView;
    TextView addressTextView;
    TextView priceTextView;
    TextView hoursTextView;
    TextView categoryTextView;
    TextView cuisineTextView;
    TextView happyHourTextView;
    TextView lunchDealTextView;
    TextView newPlaceTextView;
    ConstraintLayout constraintUpperColorSection;
    CardView cardView;
    ImageView backgroundCircleImageView;
    ImageView emojiImageView;
    Button websiteTextView;
    CheckBox checkBox;

    ViewHolder(View itemView) {
      super(itemView);
      nameTextView = itemView.findViewById(R.id.location_name_tv);
      addressTextView = itemView.findViewById(R.id.location_description_tv);
      priceTextView = itemView.findViewById(R.id.location_price_tv);
      hoursTextView = itemView.findViewById(R.id.location_hours_tv);
      backgroundCircleImageView = itemView.findViewById(R.id.background_circle);
      emojiImageView = itemView.findViewById(R.id.emoji);
      constraintUpperColorSection = itemView.findViewById(R.id.constraint_upper_color);
      categoryTextView = itemView.findViewById(R.id.location_type_tv);
      cuisineTextView = itemView.findViewById(R.id.location_cuisine_tv);
      happyHourTextView = itemView.findViewById(R.id.happyhour_tv);
      lunchDealTextView = itemView.findViewById(R.id.lunchdeal_tv);
      cardView = itemView.findViewById(R.id.map_view_location_card);
      websiteTextView = itemView.findViewById(R.id.website);
      newPlaceTextView = itemView.findViewById(R.id.new_place);
      cardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
          clickListener.onItemClick(getLayoutPosition());
        }
      });

      checkBox = itemView.findViewById(R.id.checkBox);
      checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    onCheckedChangeListener.onCheckboxClick(getLayoutPosition());
                }
            }});
    }
    @Override
    public void onClick(View view) {
    }


  }
}


I'm sure there is some simple solution to this, but I've been cracking my head over this for way too long now. Thanks!

【问题讨论】:

    标签: android checkbox android-recyclerview


    【解决方案1】:

    首先,您必须以编程方式检查每个项目的复选框。您的模型应该保存数据,一个简单的布尔值就可以做到。

    第二个是最棘手的一个

    checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if(buttonView.isPressed()){
                    if (isChecked ) {
                        onCheckedChangeListener.onCheckboxClick(holder.getAdapterPosition()());
                    }}
    }});
    

    你必须检查复选框是否真的被选中,以避免混淆,

    【讨论】:

      【解决方案2】:

      在您的 onBindViewHolder 中,您必须将 复选框设置为选中或未选中。如果为真,您的复选框将被选中,否则未选中, 因为每次滚动时回收器视图都会回收,因此您需要确保需要告诉适配器该特定位置需要选中或取消选中复选框。

      【讨论】:

        【解决方案3】:

        你为什么使用getLayoutPosition() 来获取复选框位置

        像这样使用holder.getAdapterPosition()

        checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        if (isChecked) {
                            onCheckedChangeListener.onCheckboxClick(holder.getAdapterPosition()());
                        }
        }});
        

        并将此侦听器移至您的onBindViewHolder()

        【讨论】:

          【解决方案4】:

          您的数据模型应该有一个布尔变量 isChecked。你也可以给它一个默认值 false。现在,在您的适配器函数 onBindViewHolder 中,您应该设置复选框前的值。

          card.checkBox.setChecked(locationCard.getIsChecked())
          

          另外,在你的 onCheckedChanged 中你应该更新你的数据

          locationCard.setIsChecked(isChecked)
          

          现在,每次您的 RecyclerView Adapter 重用和列出项目时,它都会正确设置其复选框的值。希望这会有所帮助。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-04-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-06-06
            • 1970-01-01
            • 1970-01-01
            • 2022-06-23
            相关资源
            最近更新 更多