【问题标题】:Multiple selected items RecyclerView in Activity.javaActivity.java中的多个选中项RecyclerView
【发布时间】:2016-12-20 05:09:34
【问题描述】:

我有一个RecyclerView,其中包含来自CardView 中本地JSON 的数据。当单击一个或某个项目时,我需要在所选项目上实现(更改所选项目或突出显示的背景)(如在 Line App 中编辑)但没有 Button 或 longpress。但我不想使用StateListDrawable或(使用XML),因为我有一些JSON 需要稍后处理的数据。

我的 Activity 中需要一个状态,例如布尔值或其他东西来保存我单击的每个项目,但我再也没有任何解决方案了。我已经阅读并尝试了一些教程,但它不起作用。这是我现在的活动下方:

adapter.setOnRecyclerViewClickedListener(new Adapter.OnRecyclerViewItemClickedListener() {
        @Override
        public void OnRecyclerViewItemClicked(int position) {
            boolean selectedItem = false;

            adapter.setOnRecyclerViewClickedListener(new Adapter.OnRecyclerViewItemClickedListener() {

        @Override
        public void OnRecyclerViewItemClicked(int position)  {

    /* ------ boolean variabel for adapter but still not work ----- */
            JSONObject filteredtableList= null;

            try {
                filteredtableList= new JSONObject("response").getJSONObject("tTisch");
            }
            catch (JSONException e) {
                e.printStackTrace();
            }

                if (recyclerView == null) {
                    try {
                        filteredtableList.has("true");
                        filteredtableList.put(status, true);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
                else {
                    try {
                        filteredtableList.put(status, true);

                    }
                    catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            adapter.updateData(filteredTableList);

//----------------------------------------------------
            try {
                Toast.makeText(TableActivity.this, filteredTableList.getJSONObject(position).getString("tischnr"), Toast.LENGTH_SHORT).show();
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    });

Adapter.java

public int lastCheckedPosition = -1;
.........
.........
.........
    @Override
public void onBindViewHolder(ViewHolder holder, int position) {

    if (position == lastCheckedPosition) {
        holder.itemView.setBackgroundResource(R.color.colorRedTableOcc);
    } else {
        holder.itemView.setBackgroundResource(R.color.colorTableGreen);
    }

    try {
        currItem = list.getJSONObject(position);
        holder.txt_no_table.setText(currItem.getString("tischnr"));

    } catch (JSONException e) {
        e.printStackTrace();
    }
}


@Override
public int getItemCount() {
    return list.length();
}

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    public TextView txt_no_table;

    public ViewHolder(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);

        txt_no_table = (TextView) itemView.findViewById(R.id.txt_no_table_empty);
    }

    @Override
    public void onClick(View itemView) {

        recyclerViewItemClickedListener.OnRecyclerViewItemClicked(getAdapterPosition());

        lastCheckedPosition = getAdapterPosition();
        notifyItemRangeChanged(0,list.length());
    }
}

JSON.json

..............
"t-tisch": [
            {
                "tischnr": 1,
                "departement": 1,
                "normalbeleg": 0,
                "kellner-nr": 0,
                "bezeich": "TABLE 01",
                "roomcharge": false,
                "betriebsnr": 0
            },
            {
                "tischnr": 2,
                "departement": 1,
                "normalbeleg": 0,
                "kellner-nr": 0,
                "bezeich": "TABLE 02",
                "roomcharge": false,
                "betriebsnr": 0
            },
............

这是我的 Activity 的样子

更新

现在输出:

当我单击该项目时它现在突出显示(感谢@Burhanuddin Rashid),但它仍然是我的情况的一半。我只能选择一个项目(我不能选择多个/更多项目)。单击突出显示的项目时,我需要再次取消选择。

已编辑:我尝试在我的 JSON 中编写新对象和键(上面的 JSON 代码)。在我的逻辑中,它会为每个项目是否被选中创建一个标志,但它仍然不起作用。

已编辑:这是我的日志错误:

                  --------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.example.development_laptop.vhp_restotemp, PID: 3590
              java.lang.NullPointerException: Attempt to invoke virtual method 'org.json.JSONObject org.json.JSONObject.put(java.lang.String, boolean)' on a null object reference
                  at com.example.development_laptop.vhp_restotemp.TableActivity$1.OnRecyclerViewItemClicked(TableActivity.java:74)
                  at com.example.development_laptop.vhp_restotemp.com.example.development_laptop.vhp_restotemp.recyclerview.source.Adapter$ViewHolder.onClick(Adapter.java:97)
                  at android.view.View.performClick(View.java:5198)
                  at android.view.View$PerformClick.run(View.java:21147)
                  at android.os.Handler.handleCallback(Handler.java:739)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:148)
                  at android.app.ActivityThread.main(ActivityThread.java:5417)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

【问题讨论】:

标签: java android json android-recyclerview


【解决方案1】:

您可以像这样应用 setOnClickListener:-

View itemView;
    Context context;


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.card_view, parent, false);
        this.context=parent.getContext();
        return new ViewHolder(itemView);
    }
    @Override
        public void onBindViewHolder(final ViewHolder holder, int position) {

            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        holder.linearLayout.setBackgroundColor(context.getResources().getColor(R.color.colorAccent,null));
                    }
                    else {
                        holder.linearLayout.setBackgroundColor(context.getResources().getColor(R.color.colorAccent));

                    }
                }
            });
        }

【讨论】:

  • 您是否只想突出显示选定的数字并在用户从该数字上移开手指时取消突出显示它。
  • 不,我想在选择一个或多个 CardView 时突出显示。当我单击所选项目时,它会再次取消突出显示。我的问题不清楚吗?我会再次编辑
【解决方案2】:

试试这个:

onBindViewHolder:

if (position == lastCheckedPosition) {
            holder.itemView.setBackgroundResource(R.drawable.ic_item_selection_background);
        } else {
            holder.itemView.setBackgroundResource(R.drawable.ic_item_deselection_background));
        }

这在 ViewHolder 上:

    itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        lastCheckedPosition = getAdapterPosition();
                         notifyItemRangeChanged(0,getItemCount());
                     }
                });

创建lastCheckedPosition作为全局变量

【讨论】:

  • 感谢您的回答,它的工作,但它使我的 CardView 变小了。并且选择的状态总是首先显示
  • 尝试修改此代码notifyItemRangeChanged(0,yourList.size());
  • myBackground 这是卡片视图吗?
  • Dont change cardview color 改变cardview里面视图的颜色
  • 我提供了这个代码只用于单选...你必须为多选实现不同的逻辑
【解决方案3】:

按照下面的代码:

将此代码放入您的onBindViewHolder() 方法中。

  @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {
    final DataModel dataModel = arraylist.get(position);
            final boolean isSelected = dataModel.isSelected();
            if (isSelected) {
               llParentLayout.setBackgroundColor(Color.Black);
            } else {
               llParentLayout.setBackgroundColor(Color.Green);            
            }
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    public TextView txt_no_table;
    public ViewHolder(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);

        txt_no_table = (TextView) itemView.findViewById(R.id.txt_no_table_empty);
    }

    @Override
    public void onClick(View itemView) {
final DataModel dataModel = arraylist.get(getAdapterPosition());
        recyclerViewItemClickedListener.OnRecyclerViewItemClicked(dataModel);

    }
}

在您的活动中:

adapter.setOnRecyclerViewClickedListener(new Adapter.OnRecyclerViewItemClickedListener() {
        @Override
        public void OnRecyclerViewItemClicked(DataModel dataModel) {

dataModel.setSelected(!dataModel.isSelected());
adapter.notifyDataSetChanged();


        }
    });

【讨论】:

  • cannot resolve symbol Data Model,数据模型是什么意思?
  • 您必须使用 Pojo/Model 类设置 Arraylist 中的数据并将其传递给适配器。 DataModel 是 pojo/Model 类
  • 我没有那门课。我只使用适配器和活动。也许还有另一种解决方案?
  • 一般来说,我们在一个位置有多种数据类型,所以我们应该创建一个模型类并将其设置为模型类数据并将其添加到arraylist中,然后将该arraylist传递给我们的适配器。
  • 我直接从资产文件夹中的 JSON 获取所有数据。我只使用getStringsetString 来处理我的数据。所以我没有像 setter 和 getter 之类的其他类
【解决方案4】:

我完全改变了我的代码,但它现在运行得很好,我的代码如下所示:

  1. 我将Adapter 更改为通用适配器。它不处理任何数据,但它投掷到我的活动中。

    public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
    public int lastCheckedPosition = -1;
    
    private static OnRecyclerViewItemClickedListener recyclerViewItemClickedListener;
    
    public void setOnRecyclerViewClickedListener (OnRecyclerViewItemClickedListener l) {
    recyclerViewItemClickedListener = l;
    }
    
    public interface OnRecyclerViewItemClickedListener {
      void OnRecyclerViewItemClicked(int position);
      void OnRecyclerViewItemBind(ViewHolder holder, int position);
      int OnRecyclerViewItemCount();
    
    }
    public Adapter() {
      super();
    } 
    
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
      View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.table_item_empty, parent, false);
      return new ViewHolder(v);
    }
    
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
    recyclerViewItemClickedListener.OnRecyclerViewItemBind(holder,position);
    }
    
    @Override
    public int getItemCount() {
      return recyclerViewItemClickedListener.OnRecyclerViewItemCount();
    }
    
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    
    public TextView txt_no_table;
    
    public ViewHolder(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);
    
        txt_no_table = (TextView) itemView.findViewById(R.id.txt_no_table_empty);
    }
    
    @Override
    public void onClick(View itemView) {
    
        recyclerViewItemClickedListener.OnRecyclerViewItemClicked(getAdapterPosition());
         }
       }
    }
    
  2. 而我的Activity 变成了这样:

    /*Add Click Listener*/
    adapter.setOnRecyclerViewClickedListener(new Adapter.OnRecyclerViewItemClickedListener() {
    
        @Override
        public void OnRecyclerViewItemClicked(int position)  {
            try {
                JSONObject currTable = filteredTableList.getJSONObject(position);
    
                if (currTable.has("selected")) {
                    currTable.put("selected", !currTable.getBoolean("selected"));
                } else {
                    currTable.put("selected",true);
                }
    
                adapter.notifyItemChanged(position);
            } catch (JSONException e) {
                e.printStackTrace();
            }
    
            try
            {
                Toast.makeText(TableActivity.this, filteredTableList.getJSONObject(position).getString("tischnr"), Toast.LENGTH_SHORT).show();
            }
            catch (JSONException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void OnRecyclerViewItemBind(Adapter.ViewHolder holder, int position) {
            try {
                JSONObject currTable = filteredTableList.getJSONObject(position);
    
                holder.txt_no_table.setText(currTable.getString("tischnr"));
    
                int queasy33Index = ProgramMethod.getJSONArrayIndex(queasy33List,"number2", currTable.getInt("tischnr"));
    
                if (queasy33Index >= 0) {
                    holder.txt_no_table.setText(holder.txt_no_table.getText() + "-" +  queasy33List.getJSONObject(queasy33Index).getString("key"));
                }
    
                if (currTable.has("selected") && currTable.getBoolean("selected")) {
                    holder.itemView.setBackgroundResource(R.color.colorRedTableOcc);
                } else {
                    holder.itemView.setBackgroundResource(R.color.colorTableGreen);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    
  3. 现在点击监听器保存任何状态并保存到我的 JSON 文件中的布尔值,如下所示:

感谢大家的建议和很好的回答:)

【讨论】:

    【解决方案5】:

    试试下面的代码

    里面

    public Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    

    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_image_and_text, parent, false);
    v.setOnClickListener(new MyOnClickListener());
    

    然后在任何你想要的地方创建这个类

    class MyOnClickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
           int itemPosition = recyclerView.indexOfChild(v);
           Log.e("Clicked and Position is ",String.valueOf(itemPosition));
        }
    }
    

    我以前读过有更好的方法,但我喜欢这种方法简单而不复杂。

    【讨论】:

      【解决方案6】:

      以上都是很好的答案,但我相信你会选择这个 这为您提供了比其他人更大的灵活性

       recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new SideMenuClickListener() {
                  @Override
                  public void onClick(View view, int position) {
      
                  }
      
                  @Override
                  public void onLongClick(View view, int position) {
                  }
              }));
      
      
      static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
      
              private GestureDetector gestureDetector;
              private SideMenuClickListener clickListener;
      
              public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final SideMenuClickListener clickListener) {
                  this.clickListener = clickListener;
                  gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
                      @Override
                      public boolean onSingleTapUp(MotionEvent e) {
                          return true;
                      }
      
                      @Override
                      public void onLongPress(MotionEvent e) {
                          View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
                          if (child != null && clickListener != null) {
                              clickListener.onLongClick(child, recyclerView.getChildPosition(child));
                          }
                      }
                  });
              }
      
              @Override
              public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                  View child = rv.findChildViewUnder(e.getX(), e.getY());
                  if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
                      clickListener.onClick(child, rv.getChildPosition(child));
                  }
                  return false;
              }
      
              @Override
              public void onTouchEvent(RecyclerView rv, MotionEvent e) {
              }
      
              @Override
              public void onRequestDisallowInterceptTouchEvent(boolean b) {
              }
          }
      

      【讨论】:

      • 谢谢,但我在这里尝试了另一个问题的代码。它不适合我
      • 这是 RecyclerView.OnItemTouchListener,在其他示例中使用 setOnRecyclerViewClickedListener
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-12
      • 2022-10-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多