Disable all other toggle buttons in recycler view after one is clicked

流过昼夜 提交于 2020-01-23 04:01:11

问题


I am using recyclerView to build a list of toggle buttons (like a numpad), I would like to achieve:

  • when user 'turns on' a button by clicking it, 'turns off' all other buttons

I have tried to add an onClickListener inside the view holder class, and call notifyDataSetChanged() such that onBindViewHolder(final ViewHolder holder, int position) is called and then change the state of the button.

But it doesn't work, the button clicked does not change its state.

ViewHolder

class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

    ToggleButton button;
    String id;

    public ViewHolder(View itemView) {
        super(itemView);
        button = (ToggleButton) itemView.findViewById(R.id.toggle);
        button.setOnclickListener(this);
    }

    @Override
    public void onClick(View view) {
        ((ToggleButton) view).setChecked(true);
        int pos = getAdapterPosition();
        if (pos != RecyclerView.NO_POSITION) {
            selected = pos;  //store the position of the user clicked button
            notifyDataSetChanged();
        }
    }

onBindViewHolder() in my adpater class

public void onBindViewHolder(final ViewHolder holder, int position) {
    String data = mData.get(position);
    holder.id = data;
    holder.button.setText(data);
    holder.button.setTextOn(data);
    holder.button.setTextOff(data);

    if (position != selected) { //if the button is not the user chosen one
        if (holder.button.isChecked()) { // and it's in 'ON' state
            holder.button.toggle(); // toggle it to switch 'OFF'
        }
    }

回答1:


There are a couple of things you are doing incorrectly. The ViewHolder should contain only views and not click handlers or strings etc. (The clue is in the name). You add the handlers and manipulate the views when you bind the ViewHolder to your data class.

From what I can determine, you want a simple list of toggle buttons. When one button is on, the others should turn off. The test adapter I created for you below demonstrates that.

Ideally, you would avoid notifyDataSetChanged and use the row based versions but as each time the toggle is pressed, it affects every other row, you do not really have a choice in this use case unless you keep track of the selected row.

public class TestAdapter extends RecyclerView.Adapter<TestAdapter.VH> {

public static class MyData {
    public boolean Selected = false;
    public String Text;

    public MyData(String text) {
        Text = text;
    }
}

public List<MyData> items = new ArrayList<>();

public TestAdapter() {
    this.items.add(new MyData("Item 1"));
    this.items.add(new MyData("Item 2"));
    this.items.add(new MyData("Item 3"));
}

@Override
public TestAdapter.VH onCreateViewHolder(ViewGroup parent, int viewType) {
    return new VH((
            LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.test_layout, parent, false))
    );
}

@Override
public void onBindViewHolder(TestAdapter.VH holder, int position) {
    final MyData itm = items.get(position);

    holder.button.setChecked(itm.Selected);
    holder.text.setText(itm.Text);

    holder.button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            for (MyData x: items){
                x.Selected=false;
            }
            itm.Selected = true;
            notifyDataSetChanged();
        }
    });

}

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

public class VH extends RecyclerView.ViewHolder {

    ToggleButton button;
    TextView text;

    public VH(View itemView) {
        super(itemView);
        button = itemView.findViewById(R.id.toggle);
        text = itemView.findViewById(R.id.text1);
    }
}
}

test_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:orientation="horizontal">

<ToggleButton
    android:id="@+id/toggle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

<TextView
    android:id="@+id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
</LinearLayout>



回答2:


Try setting OnCheckedChangeListener instead of 'OnclickListener`

`button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (isChecked) {
            // The toggle is enabled
        } else {
            // The toggle is disabled
        }
    }
});`

Android Doc : https://developer.android.com/guide/topics/ui/controls/togglebutton.html




回答3:


set on click listener in the onBindView and In the onClick method, first "turn off" all the toggle button by setting a parameter in the list model and then "turn on" the selected one if it is not selected.

@Override
public void onClick(View view) {

    // clear all model values to isSelected false in the list 

}


来源:https://stackoverflow.com/questions/44520390/disable-all-other-toggle-buttons-in-recycler-view-after-one-is-clicked

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!