Android 在recyclerview中滚动时更改状态的复选框

Android 在recyclerview中滚动时更改状态的复选框,android,checkbox,android-recyclerview,Android,Checkbox,Android Recyclerview,我制作了一个小应用程序,它向我显示了手机上安装的所有应用程序的列表。我想在每个cardview中添加一个复选框,以便我可以标记我最喜欢的应用程序和其他分类。问题是当在列表中滚动时,复选框的状态会发生变化。例如,我选中了chrome,当我向下滚动然后向上滚动时,chrome没有标记,并且选中了随机应用程序。我搜索了与这个问题相关的其他问题,但这些解决方案都不适合我 appsadapter.java的更新版本 public class AppsAdapter extends RecyclerVie

我制作了一个小应用程序,它向我显示了手机上安装的所有应用程序的列表。我想在每个cardview中添加一个复选框,以便我可以标记我最喜欢的应用程序和其他分类。问题是当在列表中滚动时,复选框的状态会发生变化。例如,我选中了chrome,当我向下滚动然后向上滚动时,chrome没有标记,并且选中了随机应用程序。我搜索了与这个问题相关的其他问题,但这些解决方案都不适合我

appsadapter.java的更新版本

 public class AppsAdapter extends RecyclerView.Adapter<AppsAdapter.ViewHolder>{
private final SparseBooleanArray array=new SparseBooleanArray();

public class ViewHolder extends RecyclerView.ViewHolder{

    public CardView cardView;
    public ImageView imageView;
    public TextView textView_App_Name;
    public CheckBox checkBox;

    public ViewHolder (View view){

        super(view);
        checkBox = (CheckBox) view.findViewById(R.id.chckbox);
        cardView = (CardView) view.findViewById(R.id.card_view);
        imageView = (ImageView) view.findViewById(R.id.imageview);
        textView_App_Name = (TextView) view.findViewById(R.id.Apk_Name);
        //textView_App_Package_Name = (TextView) view.findViewById(R.id.Apk_Package_Name);

    }
}

private Context context1;
private List<String> stringList;

public AppsAdapter(Context context, List<String> list){

    context1 = context;
    stringList = list;
}

//viewholder initialized
@Override
public AppsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){

    View view2 = LayoutInflater.from(context1).inflate(R.layout.cardview_layout,parent,false);
    ViewHolder viewHolder = new ViewHolder(view2);
    return viewHolder;
}

//DATA IS BOUND TO VIEWS
private SparseBooleanArray sba = new SparseBooleanArray();
@Override
public void onBindViewHolder(ViewHolder viewHolder,final int position){

    viewHolder.setIsRecyclable(false);
    ApkInfoExtractor apkInfoExtractor = new ApkInfoExtractor(context1);
    final String ApplicationPackageName = (String) stringList.get(position);

    //calling apps name and icon
    String ApplicationLabelName = apkInfoExtractor.GetAppName(ApplicationPackageName);
    Drawable drawable = apkInfoExtractor.getAppIconByPackageName(ApplicationPackageName);

    //setting app name and icon for every card
    viewHolder.textView_App_Name.setText(ApplicationLabelName);
    viewHolder.imageView.setImageDrawable(drawable);
    viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            sba.put(position, !sba.get(position));
            notifyDataSetChanged();
        }
    });
    viewHolder.checkBox.setChecked(sba.get(position));


    /*Adding click listener on CardView to open clicked application directly from here
    viewHolder.cardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            Intent intent = context1.getPackageManager().getLaunchIntentForPackage(ApplicationPackageName);
            if(intent != null){
                context1.startActivity(intent);
            }
            else {
                Toast.makeText(context1,ApplicationPackageName + " Error, Please Try Again.", Toast.LENGTH_LONG).show();
            }
        }
    });*/
}

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

在BindViewholder方法中设置ViewOnClickListener,以便可以使用项目的当前位置,如中所示

 private SparseBooleanArray sba = new SparseBooleanArray();
    @Override
    public void onBindViewHolder(ViewHolder viewHolder,final int position){

        viewHolder.setIsRecyclable(false);
        ApkInfoExtractor apkInfoExtractor = new ApkInfoExtractor(context1);
        final String ApplicationPackageName = (String) stringList.get(position);

        //calling apps name and icon
        String ApplicationLabelName = apkInfoExtractor.GetAppName(ApplicationPackageName);
        Drawable drawable = apkInfoExtractor.getAppIconByPackageName(ApplicationPackageName);

        //setting app name and icon for every card
        viewHolder.textView_App_Name.setText(ApplicationLabelName);
        viewHolder.imageView.setImageDrawable(drawable);
        viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    sba.put(position,!sba.get(position));
                    notifyDataSetChanged();
                }
            });
        viewHolder.checkBox.setChecked(sba.get(position));
    }
在BindViewholder方法中设置view onclicklistener,以便可以使用项的当前位置,如中所示

 private SparseBooleanArray sba = new SparseBooleanArray();
    @Override
    public void onBindViewHolder(ViewHolder viewHolder,final int position){

        viewHolder.setIsRecyclable(false);
        ApkInfoExtractor apkInfoExtractor = new ApkInfoExtractor(context1);
        final String ApplicationPackageName = (String) stringList.get(position);

        //calling apps name and icon
        String ApplicationLabelName = apkInfoExtractor.GetAppName(ApplicationPackageName);
        Drawable drawable = apkInfoExtractor.getAppIconByPackageName(ApplicationPackageName);

        //setting app name and icon for every card
        viewHolder.textView_App_Name.setText(ApplicationLabelName);
        viewHolder.imageView.setImageDrawable(drawable);
        viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    sba.put(position,!sba.get(position));
                    notifyDataSetChanged();
                }
            });
        viewHolder.checkBox.setChecked(sba.get(position));
    }

这是因为在recycler视图中,项目视图被重新用于显示新数据。您必须在数据项中添加一个变量,该变量将复选框的状态保存在特定位置。然后,在onBindViewHolder中,您可以检查跟踪变量的值并设置复选框的状态,就像您的复选框一样。setcheckeditem.getSelected在onCheckChanged方法中设置跟踪变量值,这是因为在recycler视图中,项目视图被重新用于显示新数据。您必须在数据项中添加一个变量,该变量将复选框的状态保存在特定位置。然后,在onBindViewHolder中,您可以检查跟踪变量的值并设置复选框的状态,如yourCheckbox.setcheckeditem.getSelected在onCheckChanged方法中设置跟踪变量值

holder.mCheckBox.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            CheckBox checkBox = (CheckBox) view;
            mDataModel = (DataModel) checkBox.getTag();
            mDataModel.setChecked(checkBox.isChecked());
            arrayList.get(position).setChecked(checkBox.isChecked());

        }
    });

在复选框内设置复选框onclickListener

holder.mCheckBox.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            CheckBox checkBox = (CheckBox) view;
            mDataModel = (DataModel) checkBox.getTag();
            mDataModel.setChecked(checkBox.isChecked());
            arrayList.get(position).setChecked(checkBox.isChecked());

        }
    });


你好,先生!我使用了你的代码,它给出了一个错误,说“局部变量位置是从内部类中的with访问的,需要声明为final”,所以我将int位置更改为final int位置以解决错误,但复选框问题仍然存在。问题仍然存在。添加final将删除代码中的错误,但复选框的状态仍在更改。我将代码替换为final,它的错误是“puint,booleanin SparceBooleanArray不能应用于boolean”,这并不能解决问题。复选框仍在更改,很高兴我能帮上忙!快乐编码:你好,先生!我使用了你的代码,它给出了一个错误,说“局部变量位置是从内部类中的with访问的,需要声明为final”,所以我将int位置更改为final int位置以解决错误,但复选框问题仍然存在。问题仍然存在。添加final将删除代码中的错误,但复选框的状态仍在更改。我将代码替换为final,它的错误是“puint,booleanin SparceBooleanArray不能应用于boolean”,这并不能解决问题。复选框仍在更改,很高兴我能帮上忙!快乐编码:在将adapter设置到recylerview mRecyclerView.setItemViewCacheSizeyourList.size之前,尝试在活动中添加此行@MohammedFarhan,你能解释一下这一行的作用是什么吗?每9个项目后,RecylerView recyles的视图是相同的。因此,如果您要传递给适配器的数据集包含9个以上的项,并且对特定项所做的更改Checking复选框将在9个项之后重新出现。因此,如果您添加该行,它将设置在将其添加到可能共享的循环视图池之前要保留的屏幕外视图的数量。屏幕外视图缓存将保持对所连接适配器中的更改的感知。在将适配器设置为recylerview mRecyclerView.setItemViewCacheSizeyourList.size之前,请尝试在“活动”中添加此行@MohammedFarhan,你能解释一下这一行的作用是什么吗?每9个项目后,RecylerView recyles的视图是相同的。因此,如果您要传递给适配器的数据集包含9个以上的项,并且对特定项所做的更改Checking复选框将在9个项之后重新出现。因此,如果您添加该行,它将设置在将其添加到可能共享的循环视图池之前要保留的屏幕外视图的数量。屏幕外的视图缓存会随时注意所连接适配器中的更改。您好!你能给我一个简单的代码,我可以遵循吗?对不起打扰你了嗨!你能给我一个简单的代码,我可以遵循吗?对不起打扰你了