【问题标题】:Disable all other toggle buttons in recycler view after one is clicked单击一个后禁用回收器视图中的所有其他切换按钮
【发布时间】:2017-06-13 11:34:37
【问题描述】:

我正在使用 recyclerView 构建一个切换按钮列表(如小键盘),我想实现:

  • 当用户通过单击“打开”按钮时,会“关闭”所有其他按钮

我试图在视图持有者类中添加一个onClickListener,并调用notifyDataSetChanged(),以便调用onBindViewHolder(final ViewHolder holder, int position),然后更改按钮的状态。

但它不起作用,点击的按钮不会改变它的状态。

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();
        }
    }

我的 adpater 类中的 onBindViewHolder()

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'
        }
    }

【问题讨论】:

  • 所以你需要一次打开一个按钮。是吗?
  • 避免使用 notifyDataSetChanged(),而是尽可能使用 notifyItemChanged(pos),我认为 notifyItemChanged(int pos) 适合您的要求,因为一次单个项目处于活动状态。跨度>

标签: java android android-recyclerview toggle


【解决方案1】:

有几件事你做错了。 ViewHolder 应该只包含视图,而不是单击处理程序或字符串等。(线索在名称中)。当您将 ViewHolder 绑定到您的数据类时,您可以添加处理程序并操作视图。

据我所知,您需要一个简单的切换按钮列表。当一个按钮打开时,其他按钮应该关闭。我在下面为您创建的测试适配器证明了这一点。

理想情况下,您应该避免使用notifyDataSetChanged 并使用基于行的版本,但每次按下切换按钮时,它都会影响其他每一行,除非您跟踪选定的行,否则您在此用例中实际上没有选择余地行。

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>

【讨论】:

  • 我试过你的代码,我得到这个异常 java.lang.IllegalStateException: Cannot call this method while RecyclerView 正在计算布局或滚动。当 bindingView 已经在运行时,您不能调用 notifyDataSetChanged。您可以使用标志来指示绑定是否正在运行,或者使用处理程序在不同的线程上运行 notifyDataSetChanged。
  • 这是一个 recyclerview 适配器的最基本演示,当我编写它时它运行良好。也许您自己的代码会造成副作用。试试看这个:stackoverflow.com/questions/27070220/…
【解决方案2】:

尝试设置 OnCheckedChangeListener 而不是 '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 文档:https://developer.android.com/guide/topics/ui/controls/togglebutton.html

【讨论】:

    【解决方案3】:

    在 onBindView 和 onClick 方法中设置点击监听器, 首先通过在列表模型中设置参数来“关闭”所有切换按钮 如果未选中,则“打开”选中的那个。

    @Override
    public void onClick(View view) {
    
        // clear all model values to isSelected false in the list 
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-02
      • 1970-01-01
      • 2012-06-02
      • 2022-12-20
      • 1970-01-01
      • 2019-01-18
      • 1970-01-01
      • 2019-02-01
      相关资源
      最近更新 更多