繁体   English   中英

应用程序列表recyclerview复选框更改状态

[英]App List recyclerview check box changing state

我制作了一个应用程序,其中列出了您设备中所有已安装应用程序的清单,并在recyclerview中添加了一个复选框,以在列表中选择一个应用程序(我将以该应用程序作为应用程序阻止程序的基础)。 问题在于,上下滚动时,复选框状态始终会更改。 恩。 我检查了facebook,然后向下滚动;当我向上滚动时,facebook被取消选中,有时还检查了一个随机应用程序。

这是我的代码:

ApkInfoextractor:

public class ApkInfoExtractor {

    Context context1;

    public ApkInfoExtractor(Context context2){

        context1 = context2;
    }

    public List<String> GetAllInstalledApkInfo(){

        List<String> ApkPackageName = new ArrayList<>();

        Intent intent = new Intent(Intent.ACTION_MAIN,null);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED );

        //Information that is returned from resolving an intent against an IntentFilter
        List<ResolveInfo> resolveInfoList = context1.getPackageManager().queryIntentActivities(intent,0);

        for(ResolveInfo resolveInfo : resolveInfoList){
            ActivityInfo activityInfo = resolveInfo.activityInfo;

            if(!isSystemPackage(resolveInfo)){

                ApkPackageName.add(activityInfo.applicationInfo.packageName);
            }
        }
        return ApkPackageName;
    }

    public boolean isSystemPackage(ResolveInfo resolveInfo){
        return ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
    }

    public Drawable getAppIconByPackageName(String ApkTempPackageName){
        Drawable drawable;

        try{
            drawable = context1.getPackageManager().getApplicationIcon(ApkTempPackageName);
        }
        catch (PackageManager.NameNotFoundException e){

            e.printStackTrace();
            drawable = ContextCompat.getDrawable(context1, R.mipmap.ic_launcher);
        }
        return drawable;
    }

    public String GetAppName(String ApkPackageName){

        String Name = "";
        ApplicationInfo applicationInfo;
        PackageManager packageManager = context1.getPackageManager();

        try {

            applicationInfo = packageManager.getApplicationInfo(ApkPackageName, 0);

            if(applicationInfo!=null){
                Name = (String)packageManager.getApplicationLabel(applicationInfo);
            }

        }catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return Name;
    }
}

AppsAdapter:

public class AppsAdapter extends RecyclerView.Adapter<AppsAdapter.ViewHolder>{

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

    private SparseBooleanArray sba = new SparseBooleanArray();

    //DATA IS BOUND TO VIEWS
    @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);

        //saving states of the checkbox
        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));

    }

    //viewholder
    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);

        }
    }

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

我已经尝试了Google的许多解决方案,但都没有为我工作。 因此,详细的答案会有所帮助(非常感谢示例代码或其他参考资料。)

可以使用Set代替SparseBooleanArray

    HashSet<Integer> selection = new HashSet<>();

在onBind方法中,请使用以下代码,也请使用标记,而不是最终确定位置

//saving states of the checkbox
        viewHolder.itemView.setTag(position);
        viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos = (int) v.getTag();
                if (selection.contains(pos))
                    selection.remove(pos);
                else 
                    selection.add(pos);
                notifyDataSetChanged();
            }
        });
        viewHolder.checkBox.setChecked(selection.contains(position));

我也发生了过去两年的问题。 但是我通过使用HashMap克服了这个问题。 将布尔值保存在Hash Map上单击位置的项目。 onBindViewHolder HashMap onBindViewHolder

可以引用我的ConsistantRecylerAdapter

将您的视图持有人更改为

         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);
           this.setIsRecyclable(false);
        }

该声明:

 this.setIsRecyclable(false);

这只是解决方法,可能会阻止回收者视图不重用单元

经过大量研究,我已经遇到了完全相同的问题,并已解决。 这样做的原因是每次滚动列表时都会在回收视图中使用回收列表项(再次创建创建的数据),从而丢失其实例,与Textview或edittext不同,诸如Checkbox之类的视图不保存其数据。

您可以尝试按照以下方式解决此问题:

单击复选框后,将值保存在模型类中,然后在onCreate内检查JSON模型类中的内容,并将其分配给复选框

onCreate:

if(model.isChecked)) {
    checkbox.setChecked(true);

}else{
checkbox.setChecked(false);

}

然后在复选框上单击:

checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
       model.setIsChecked(isChecked);
    }

我确定这可以解决您的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM