当我滚动时自动选中/取消选中复选框的回收器视图



这是我QuestionHolder

 private class QuestionHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    private JSONObject question;
    private CheckBox checkBox;
    private TextView question_txt;
    public QuestionHolder(final LayoutInflater inflater, ViewGroup parent) {
        super(inflater.inflate(R.layout.question_item, parent, false));
        checkBox  = (CheckBox) itemView.findViewById(R.id.question_checkbox);
        checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //try {
                    //Toast.makeText(getActivity(), "ID: " + question.get("_id"), Toast.LENGTH_SHORT).show();
                //} catch (JSONException e) { }
                // TODO: If this was checked then add the question's id to the answered list
            }
        });
        question_txt = (TextView) itemView.findViewById(R.id.question);
        itemView.setOnClickListener(this);
    }

在这里我绑定questiontxt

public void bind(JSONObject question) {
  this.question = question;
  try {
    question_txt.setText(question.getString("_question"));
  } catch (JSONException je) { }
}
@Override
public void onClick(View v) {
  // TODO: If this was checked then add the question's id to the answered list
}
}

这是我的适配器,它扩展了QuestionHolder

private class QuestionAdapter extends RecyclerView.Adapter<QuestionHolder> {
    private JSONArray questions;
    public QuestionAdapter(JSONArray questions) {
        this.questions = questions;
    }
    @Override
    public QuestionHolder onCreateViewHolder(ViewGroup parent, int viewType) 
{
        return new QuestionHolder(LayoutInflater.from(getActivity()), parent);
    }

这是onBindViewHolder

@Override
public void onBindViewHolder(QuestionHolder holder, int position) {
  try {
    final JSONObject question = questions.getJSONObject(position);
    holder.bind(question);
  } catch (JSONException je) { }
}
@Override
public int getItemCount() {
  return questions.length();
}
}

这是QuestionHolder

private class QuestionHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    private JSONObject question;
    private CheckBox checkBox;
    private TextView question_txt;
    public QuestionHolder(final LayoutInflater inflater, ViewGroup parent) {
        super(inflater.inflate(R.layout.question_item, parent, false));
        checkBox  = (CheckBox) itemView.findViewById(R.id.question_checkbox);
        checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //try {
                    //Toast.makeText(getActivity(), "ID: " + question.get("_id"), Toast.LENGTH_SHORT).show();
                //} catch (JSONException e) { }
                // TODO: If this was checked then add the question's id to the answered list
            }
        });
        question_txt = (TextView) itemView.findViewById(R.id.question);
        itemView.setOnClickListener(this);
    }
    public void bind(JSONObject question) {
        this.question = question;
        try {
            question_txt.setText(question.getString("_question"));
        } catch (JSONException je) { }
    }
    @Override
    public void onClick(View v) {
        // TODO: If this was checked then add the question's id to the answered list
    }
}

这是因为您的ViewHolder在滚动时被回收。因此,您需要为每个项目位置保留复选框的状态。您可以使用 SparseBooleanArray 来处理此问题。

你可以做这样的事情:

private class QuestionAdapter extends RecyclerView.Adapter<QuestionHolder> {
  SparseBooleanArray checkedItems = new SparseBooleanArray();
  ...
  @Override
  public void onBindViewHolder(QuestionHolder holder, int position) {
    try {
      final JSONObject question = questions.getJSONObject(position);
      // Remember to change access modifier of checkBox in your ViewHolder
      // Get the state from checkedItems. If no previous value, it will return false.
      holder.checkBox.setChecked(checkedItems.get(position));
      // This is a sample. Do not use create listener here.
      checkBox.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
          // save the check state
          checkedItems.put(position, true);
        }
      holder.bind(question);
    } catch (JSONException je) { }
  }
  ...
}

RecyclerView 在滚动时从布局中删除(回收(不可见的视图,这是 recyclerView 的基本行为,以减少内存使用。

因此,当带有复选框的视图被"回收"时,选中的复选框将被取消选中,如果它有侦听器,则会调用侦听器。

回收侦听器

时,可以从视图中删除侦听器。只需覆盖 onViewRecycling 方法即可。

 @Override
    public void onViewRecycled(@NonNull MyViewHolder holder) {
        if (holder.checkBox != null) {
            holder.checkBox.setOnClickListener(null);
        }
        super.onViewRecycled(holder);
    }

当再次构建视图时,在滚动时,您的侦听器也将再次添加。

在对这个复杂问题进行一些研究之后

我为我的货币转换器项目做了这样的事情:

以下是步骤:

  1. 创建了一个带有内部视图持有人的自定义适配器
  2. 创建了选择的干扰更改并通知Adaper in MainActivty
  3. 已创建模型类 为"我的列表"创建了布局

编码:

适配器和视图支架

    class Adapter extends RecyclerView.Adapter<Adapter.VH> {
    ArrayList<Currency> list, checkedCurrencies = new ArrayList<>();
    CurrencySelectionChangelistener listener;

    public Adapter(@NonNull ArrayList<Currency> list, CurrencySelectionChangelistener listener) {
        this.list = list;
        this.listener = listener;
    }
    @NonNull
    @Override
    public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new VH(LayoutInflater.from(getContext()).inflate(R.layout.layout_list_of_all_items, parent, false));
    }
    @Override
    public void onBindViewHolder(@NonNull VH holder, @SuppressLint("RecyclerView") int position) {
        Currency currentCurrency = list.get(position);
        holder.checkBox.setChecked(currentCurrency.isChecked());
        holder.mDis.setText(currentCurrency.getDescription());
        //ignore below line it's just for sorting the string to set On TextView and with another purpose
        String name = currentCurrency.getName().toLowerCase().replace(" ", "");
        holder.mName.setText(name.toUpperCase());
        holder.mLogo.setImageResource(currentCurrency.getLogo(name));
        holder.checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (holder.checkBox.isChecked()) {
                    list.get(position).setChecked(true);
                    checkedCurrencies.add(currentCurrency);
                } else if (!holder.checkBox.isChecked()) {
                    list.get(position).setChecked(false);
                    checkedCurrencies.remove(currentCurrency);
                }
                //calling the interference's function
                onSelection(checkedCurrencies);
            }
        });

    }
    @Override
    public int getItemCount() {
        return list.size();
    }
    class VH extends RecyclerView.ViewHolder {
        TextView mName, mDis;
        ImageView mLogo;
        CheckBox checkBox;
        public VH(@NonNull View itemView) {
            super(itemView);
            checkBox = itemView.findViewById(R.id.checkboxAllItems);
            mLogo = itemView.findViewById(R.id.ImageViewAllItemLogo);
            mName = itemView.findViewById(R.id.textViewAllItemCName);
            mDis = itemView.findViewById(R.id.textViewAllItemCDis);
        }
    }
}

接口

public interface CurrencySelectionChangelistener {
public void onSelection(ArrayList<Currency> currencies);}

我正在使用回收器视图的片段

public class AddMoreCurrencyFragment extends Fragment implements CurrencySelectionChangelistener {
FragmentAddNewCurrencyBinding binding;
ArrayList<Currency> currencies;
Adapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    binding = FragmentAddNewCurrencyBinding.inflate(inflater);
    CurrencyContainerActivity.title.setVisibility(View.VISIBLE);
    CurrencyContainerActivity.title.setText("Add Currency");
    CurrencyContainerActivity.backBtn.setVisibility(View.VISIBLE);
    currencies = new ArrayList<>();
    for (Currency c : CurrencyContainerActivity.listOfCurrencies) {
        currencies.add(new Currency(c.getName(), c.getDescription(), false));
    }
    adapter = new Adapter(currencies, this);
    binding.recView.setAdapter(adapter);

    binding.done.setOnClickListener(view -> {
    });
    return binding.getRoot();
}

@Override
public void onSelection(ArrayList<Currency> currencies) {
    CurrencyContainerActivity.listToAdd.addAll(currencies);
    Toast.makeText(getContext(), currencies.toString(), Toast.LENGTH_LONG).show();
    adapter.notifyDataSetChanged();
}

}

每个项目的 XML 布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:background="@color/white"
    android:orientation="vertical"
    android:weightSum="3">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="59dp"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:padding="10dp"
        android:weightSum="3">
        <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0.89"
            app:cardCornerRadius="16dp">
            <ImageView
                android:id="@+id/ImageViewAllItemLogo"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/flag" />
        </androidx.cardview.widget.CardView>
        <TextView
            android:id="@+id/textViewAllItemCName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="19dp"
            android:layout_weight=".75"
            android:fontFamily="@font/poppins"
            android:text="@string/pkr"
            android:textAlignment="center"
            android:textAllCaps="true"
            android:textColor="@color/black"
            android:textSize="16sp" />
        <TextView
            android:id="@+id/textViewAllItemCDis"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginEnd="10dp"
            android:layout_weight="0.47"
            android:fontFamily="@font/poppins"
            android:text="@string/pkr"
            android:textAlignment="textStart"
            android:textColor="@color/black"
            android:textSize="13sp" />
        <CheckBox
            android:id="@+id/checkboxAllItems"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_weight="0.90"
            android:background="@drawable/radio_selector"
            android:button="@android:color/transparent" />
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#3F000000" />
</LinearLayout>

模型类

public class Currency {
    private String Name, Description;
    private int logo;
    boolean isChecked;
    public Currency(String name, String description, boolean isChecked) {
        Name = name;
        Description = description;
        this.isChecked = isChecked;
    }
    public boolean isChecked() {
        return isChecked;
    }
    public void setChecked(boolean checked) {
        isChecked = checked;
    }
    public String getName() {
        return Name;
    }
    public void setName(String name) {
        Name = name;
    }
    public String getDescription() {
        return Description;
    }
    public void setDescription(String description) {
        Description = description;
    }
    
}

如果我错过了什么,可以。谢谢

最新更新