1. ホーム
  2. android

[解決済み] RecyclerViewの単一選択

2023-04-17 19:02:31

質問

にデフォルトの選択メソッドがないことは知っています。 RecyclerView クラスにはデフォルトの選択メソッドがないことは知っていますが、以下の方法で試してみました。

public void onBindViewHolder(ViewHolder holder, final int position) {
    holder.mTextView.setText(fonts.get(position).getName());
    holder.checkBox.setChecked(fonts.get(position).isSelected());

    holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if(isChecked) {
                for (int i = 0; i < fonts.size(); i++) {
                    fonts.get(i).setSelected(false);
                }
                fonts.get(position).setSelected(isChecked);
            }
        }
    });
}

このコードを試している間、私は期待された出力を得ましたが、完全ではありません。

画像で説明します。

デフォルトでは、私のアダプタから最初の項目が選択されます。

次に、2番目、3番目、4番目、最後に5番目を選択します。

ここでは、5番目だけが選択されるはずですが、5つとも選択されています。

リストを一番下までスクロールして、もう一度一番上に戻ってくると、期待通りのものが表示されます。

どうすればこの問題を解決できますか?また、リストを非常に速くスクロールした場合、他の項目が選択されることがあります。この問題もどのように克服できますか?

を使おうとしていたとき、私は notifyDataSetChanged() の後に fonts.get(position).setSelected(isChecked); の後に、次のような例外が発生しました。

java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
        at android.support.v7.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:1462)
        at android.support.v7.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:2982)
        at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:7493)
        at android.support.v7.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:4338)
        at com.app.myapp.screens.RecycleAdapter.onRowSelect(RecycleAdapter.java:111)

どのように解決するのですか?

問題の解決方法です。

public class yourRecyclerViewAdapter extends RecyclerView.Adapter<yourRecyclerViewAdapter.yourViewHolder> {

    private static CheckBox lastChecked = null;
    private static int lastCheckedPos = 0;


    public void onBindViewHolder(ViewHolder holder, final int position) {
    
        holder.mTextView.setText(fonts.get(position).getName());
        holder.checkBox.setChecked(fonts.get(position).isSelected());
        holder.checkBox.setTag(new Integer(position));

        //for default check in first item
        if(position == 0 && fonts.get(0).isSelected() && holder.checkBox.isChecked())
        {
           lastChecked = holder.checkBox;
           lastCheckedPos = 0;
        }
           
        holder.checkBox.setOnClickListener(new View.OnClickListener() 
        {
            @Override
            public void onClick(View v) 
            {
               CheckBox cb = (CheckBox)v;
               int clickedPos = ((Integer)cb.getTag()).intValue(); 

               if(cb.isChecked())
               {
                  if(lastChecked != null)
                  {
                      lastChecked.setChecked(false);
                      fonts.get(lastCheckedPos).setSelected(false);
                  }                       
                 
                  lastChecked = cb;
                  lastCheckedPos = clickedPos;
              }
              else
                 lastChecked = null;

              fonts.get(clickedPos).setSelected(cb.isChecked);
           }
       });
    }
}