如何在RecyclerView的OnClickListener中管理多个位置

huangapple go评论60阅读模式
英文:

How to manage multiple positions in RecyclerView OnClickListener

问题

我想知道如何在此 OnClickListener 中访问数组的其他元素,用于 RecyclerView 的点击事件。具体而言,我想能够在点击事件内部更改除当前监听位置之外的其他位置的启用状态。

我正在尝试的是,如果选中了三种颜色(这些是复选框),则未选中的每个框将被禁用,直到选中的框的数量小于 3。

我写的循环 for 看起来是有道理的,但出于某种原因,我不能在 onClickListener 中以编程方式更改启用状态。

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(new ExampleAdapter.OnItemClickListener() {
        @Override
        public void onItemClick(int position) {

            boolean checkedState;

            if (mExampleList.get(position).getChecked1() == false) {

                checkedState = true;

            } else {

                checkedState = false;

            }

            changeItem(position, checkedState);

            int sum = 0;

            for (int i = 0; i < stringArray.length; i++) {

                Boolean checked = mExampleList.get(i).getChecked1();

                if (checked == true) {

                    sum = sum + 1;

                }

            }

            for (int i = 0; i < stringArray.length; i++) {

                Boolean checked = mExampleList.get(i).getChecked1();

                if (!checked && sum == 3) {

                    mExampleList.get(i).setEnabled1(false);

                } else {

                    mExampleList.get(i).setEnabled1(true);

                }

            }

        }

    });

}

适配器:

public class ExampleAdapter extends RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder> {

    private ArrayList<ExampleItem> mExampleList;
    private OnItemClickListener mListener;

    // ...(略去其他部分)
}

项目类:

public class ExampleItem {

    // ...(略去其他部分)
}

换句话说,我试图在取消选中红色、绿色或蓝色之前,使蓝色以下的所有内容都被禁用!

英文:

I want to know how I can get access to other elements of the array in this onclicklistener for a Recycler view. Specifically, I want to be able to change the enabled state of a position other than the current Listener position, but within the click event.

I'm trying to make it such that if three colors are checked (those are check boxes) every box not checked will be disabled until the number of boxes checked is < 3.

The for-loops I have I wrote make sense, but I can't programmatically change the enabled state within the onClickListener for some reason.

  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(new ExampleAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position) {
boolean checkedState;
if (mExampleList.get(position).getChecked1() == false) {
checkedState = true;
} else {
checkedState = false;
}
changeItem(position, checkedState);
int sum = 0;
for (int i = 0; i &lt; stringArray.length; i++) {
Boolean checked = mExampleList.get(i).getChecked1();
if (checked == true) {
sum = sum + 1;
}
}
for (int i = 0; i &lt; stringArray.length; i++) {
Boolean checked = mExampleList.get(i).getChecked1();
if (!checked &amp;&amp; sum == 3) {
mExampleList.get(i).setEnabled1(false);
} else {
mExampleList.get(i).setEnabled1(true);
}
}
}
});
}

adapter

public class ExampleAdapter extends RecyclerView.Adapter&lt;ExampleAdapter.ExampleViewHolder&gt; {
private ArrayList&lt;ExampleItem&gt; mExampleList;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public static class ExampleViewHolder extends RecyclerView.ViewHolder {
public CheckBox mCheckBox;
public ExampleViewHolder(@NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
mCheckBox = itemView.findViewById(R.id.checkBox);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION);
listener.onItemClick(position);
}
}
});
}
}
public ExampleAdapter(ArrayList&lt;ExampleItem&gt; exampleList) {
mExampleList = exampleList;
}
@NonNull
@Override
public ExampleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.example_item, parent, false);
ExampleViewHolder evh = new ExampleViewHolder(v, mListener);
return evh;
}
@Override
public void onBindViewHolder(@NonNull ExampleViewHolder holder, int position) {
ExampleItem currentItem = mExampleList.get(position);
holder.mCheckBox.setText(currentItem.getCheckText());
holder.mCheckBox.setEnabled(currentItem.getEnabled1());
holder.mCheckBox.setChecked(currentItem.getChecked1());
}
@Override
public int getItemCount() {
return mExampleList.size();
}
}

Item Class

public class ExampleItem {
public String mCheckText;
public Boolean mEnabled;
public Boolean mChecked;
public ExampleItem(String mCheckText, Boolean mEnabled, Boolean mChecked) {
this.mCheckText = mCheckText;
this.mEnabled = mEnabled;
this.mChecked = mChecked;
}
public ExampleItem(String mCheckText) {
this.mCheckText = mCheckText;
}
public String getCheckText() {
return mCheckText;
}
public void setCheckText(String mCheckText) {
this.mCheckText = mCheckText;
}
public Boolean getEnabled1() {
return mEnabled;
}
public void setEnabled1(Boolean mEnabled) {
this.mEnabled = mEnabled;
}
public Boolean getChecked1() {
return mChecked;
}
public void setChecked1(Boolean mChecked) {
this.mChecked = mChecked;
}
}

如何在RecyclerView的OnClickListener中管理多个位置

In other words, I am trying to make everything below blue disabled until I uncheck Red, Green, or Blue!

答案1

得分: 0

你需要在Adapter类中为'mExampleList'创建一个setter函数,以便更新适配器正在使用的数据集。如果您在活动中对'mExampleList'进行更改而不更新Adapter使用的列表,那么显然不会产生任何变化。

因此,在点击监听器的最后,您会有类似以下的代码:

mAdapter.setExampleList(mExampleList);
mAdapter.notifyDataSetChanged();
英文:

You would need to create a setter function for your 'mExampleList' in your Adpater class, to update the dataset that the adapter is using. It obviously does not change anything, if you make changes to 'mExampleList' in your activity, without updating the list used by the Adapter.

So at the end of your click listener you would have something like that:

mAdapter.setExampleList(mExampleList)
mAdapter.notifyDataSetChanged()

答案2

得分: 0

在适配器中,添加以下代码:

private int selectedCount = 0;

public int getSelectedCount() {
    return selectedCount;
}

public void setSelectedCount(int selectedCount) {
    this.selectedCount = selectedCount;
    notifyDataSetChanged();
}

onBindViewHolder() 更改为:

@Override
public void onBindViewHolder(@NonNull ExampleViewHolder holder, int position) {

    ExampleItem currentItem = mExampleList.get(position);

    holder.mCheckBox.setText(currentItem.getCheckText());
    holder.mCheckBox.setChecked(currentItem.getChecked1());
    if ((selectedCount == 3)) holder.mCheckBox.setEnabled(currentItem.getChecked1());
    else holder.mCheckBox.setEnabled(true);
}

然后在 Activity/Fragment 中,将 mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener()... 更改为:

mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(int position) {
        boolean checkedState;
        int selectedCount = mAdapter.getSelectedCount();

        if ((selectedCount != 3) || (mExampleList.get(position).getChecked1())) {
            if (mExampleList.get(position).getChecked1() == false) {
                checkedState = true;
                selectedCount++;
            } else {
                checkedState = false;
                selectedCount--;
            }
            changeItem(position, checkedState);
            mAdapter.setSelectedCount(selectedCount);
        }
    }
});

请注意,ExampleItem 类中不需要有 mEnabled 字段。希望这对你有所帮助!

关于点击事件的说明:这是因为 CheckBox 完全覆盖了布局,所以 itemView 无法接收到点击事件。关于 RecyclerView:思路很简单,修改了数据集(不是列表,这里指的是 mExampleList 和 selectedCount),然后调用 notifyDataSetChanged(),这将重新绘制所有的 RecyclerView 子项视图。

英文:

Try the following:

In adapter, add below codes:

private int selectedCount = 0;
public int getSelectedCount() {
return selectedCount;
}
public void setSelectedCount(int selectedCount) {
this.selectedCount = selectedCount;
notifyDataSetChanged();
}

and change onBindViewHolder() to:

@Override
public void onBindViewHolder(@NonNull ExampleViewHolder holder, int position) {
ExampleItem currentItem = mExampleList.get(position);
holder.mCheckBox.setText(currentItem.getCheckText());
holder.mCheckBox.setChecked(currentItem.getChecked1());
if ((selectedCount == 3)) holder.mCheckBox.setEnabled(currentItem.getChecked1());
else holder.mCheckBox.setEnabled(true);
}

Then in Activity/Fragment, change mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener()... to:

    mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position) {
boolean checkedState;
int selectedCount = mAdapter.getSelectedCount();
if ((selectedCount != 3) || (mExampleList.get(position).getChecked1())) {
if (mExampleList.get(position).getChecked1() == false) {
checkedState = true;
selectedCount++;
} else {
checkedState = false;
selectedCount--;
}
changeItem(position, checkedState);
mAdapter.setSelectedCount(selectedCount);
}
}
});

Pls note that no need to have mEnabled field in the ExampleItem class. Hope that helps!

Explanantion:
About the onClick:- This is because CheckBox totally covered the layout, so itemView cannot recieve the click event. About RecyclerView:- The idea is simple, after modified the data set [not list, here I refer to the mExampleList and also the selectedCount], then call notifyDataSetChanged() which will redraw all recycler item views.

huangapple
  • 本文由 发表于 2020年5月5日 12:42:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/61605931.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定