简体   繁体   中英

Storing CheckBox state in ListView

I have a ListView with a CheckBox in every list item, I stored the check state with SharedPreferences , but every time I scroll with one item checked, every item is unchecked, or checked, depending on the default value when I call checkbox.setChecked(); ListViewAdapter.java

public class ListViewAdapter extends BaseAdapter {

Context context;
AppPicker.Package[] packagesForAdapter;
SharedPreferences.Editor editor;
private Intent blackListIntent;

public ListViewAdapter(Context context, AppPicker.Package packages[]) {
    this.context = context;
    this.packagesForAdapter = packages;
}

@Override
public int getCount() {
    return packagesForAdapter.length;
}

@Override
public Object getItem(int i) {
    return null;
}

@Override
public long getItemId(int i) {
    return 0;
}

static class ViewHolder {
    TextView text;
    ImageView icon;
    CheckBox checkBox;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    SharedPreferences sharedPreferences = context.getSharedPreferences("sharedPreferences", Context.MODE_PRIVATE);
    ViewHolder viewHolder;
    LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if(convertView == null) {
        convertView = layoutInflater.inflate(R.layout.list_item, null);
        viewHolder = new ViewHolder();
        viewHolder.text = (TextView) convertView.findViewById(R.id.icon_text);
        viewHolder.icon = (ImageView) convertView.findViewById(R.id.icon_image);
        viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.icon_check);

        convertView.setTag(viewHolder);
    }else{
        viewHolder = (ViewHolder) convertView.getTag();
    }

    editor = sharedPreferences.edit();

    viewHolder.icon.setImageDrawable(packagesForAdapter[position].icon);
    viewHolder.text.setText(packagesForAdapter[position].label);
    //viewHolder.checkBox.setChecked(sharedPreferences.getBoolean("CheckValue" + position, false));
    viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        int pos = position;
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
            if(isChecked) {
                Toast.makeText(context, "Item checked: " + pos + " App: " + packagesForAdapter[pos].name, Toast.LENGTH_SHORT).show();
                blackListIntent = new Intent("com.jason.floating.notification.appPickerFragment.ListViewAdapter");
                blackListIntent.putExtra("packageName", packagesForAdapter[pos].name);
            }else{
                Toast.makeText(context, "Item unchecked: " + pos + " App: " + packagesForAdapter[pos].name, Toast.LENGTH_SHORT).show();
                blackListIntent.removeExtra("packageName");
            }
            context.sendBroadcast(blackListIntent);
            editor.putBoolean("CheckValue" + pos, isChecked);
            editor.commit();
        }
    });

    return convertView;
}

}

any idea please help, cause I've been looking all over the internet but no luck /_\\

EDIT: modified code: public class ListViewAdapter extends BaseAdapter {

Context context;
AppPicker.Package[] packagesForAdapter;
SharedPreferences.Editor editor;
private Intent blackListIntent;
boolean isChecked;

public ListViewAdapter(Context context, AppPicker.Package packages[]) {
    this.context = context;
    this.packagesForAdapter = packages;
}

@Override
public int getCount() {
    return packagesForAdapter.length;
}

@Override
public Object getItem(int i) {
    return null;
}

@Override
public long getItemId(int i) {
    return 0;
}

static class ViewHolder {
    TextView text;
    ImageView icon;
    CheckBox checkBox;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    ViewHolder viewHolder;
    LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if(convertView == null) {
        convertView = layoutInflater.inflate(R.layout.list_item, null);
        viewHolder = new ViewHolder();
        viewHolder.text = (TextView) convertView.findViewById(R.id.icon_text);
        viewHolder.icon = (ImageView) convertView.findViewById(R.id.icon_image);
        viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.icon_check);

        convertView.setTag(viewHolder);
    }else{
        viewHolder = (ViewHolder) convertView.getTag();
    }

    editor = sharedPreferences.edit();

    viewHolder.icon.setImageDrawable(packagesForAdapter[position].icon);
    viewHolder.text.setText(packagesForAdapter[position].label);
    viewHolder.checkBox.setChecked(packagesForAdapter[position].isChecked);
    viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        int pos = position;
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
            if(b) {
                Toast.makeText(context, "Item checked: " + pos + " App: " + packagesForAdapter[pos].name, Toast.LENGTH_SHORT).show();
                blackListIntent = new Intent("com.jason.floating.notification.appPickerFragment.ListViewAdapter");
                blackListIntent.putExtra("packageName", packagesForAdapter[pos].name);
                packagesForAdapter[pos].isChecked = true;
                editor.commit();
            }else{
                Toast.makeText(context, "Item unchecked: " + pos + " App: " + packagesForAdapter[pos].name, Toast.LENGTH_SHORT).show();
                blackListIntent.removeExtra("packageName");
                packagesForAdapter[pos].isChecked = false;
                editor.commit();
            }
            context.sendBroadcast(blackListIntent);
            //editor.putBoolean("CheckValue" + pos, isChecked);
            //editor.commit();
        }
    });

    return convertView;
}

}

EDIT2: modified code: public class ListViewAdapter extends BaseAdapter {

Context context;
AppPicker.Package[] packagesForAdapter;
SharedPreferences.Editor editor;
private Intent blackListIntent;
boolean isChecked;

public ListViewAdapter(Context context, AppPicker.Package packages[]) {
    this.context = context;
    this.packagesForAdapter = packages;
}

@Override
public int getCount() {
    return packagesForAdapter.length;
}

@Override
public Object getItem(int i) {
    return null;
}

@Override
public long getItemId(int i) {
    return 0;
}

static class ViewHolder {
    TextView text;
    ImageView icon;
    CheckBox checkBox;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    ViewHolder viewHolder;
    LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if(convertView == null) {
        convertView = layoutInflater.inflate(R.layout.list_item, null);
        viewHolder = new ViewHolder();
        viewHolder.text = (TextView) convertView.findViewById(R.id.icon_text);
        viewHolder.icon = (ImageView) convertView.findViewById(R.id.icon_image);
        viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.icon_check);

        convertView.setTag(viewHolder);
    }else{
        viewHolder = (ViewHolder) convertView.getTag();
    }

    editor = sharedPreferences.edit();

    viewHolder.icon.setImageDrawable(packagesForAdapter[position].icon);
    viewHolder.text.setText(packagesForAdapter[position].label);
    viewHolder.checkBox.setChecked(packagesForAdapter[position].isChecked);
    viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
            /**
            if(isCheck) {
                Toast.makeText(context, "Item checked: " + pos + " App: " + packagesForAdapter[pos].name, Toast.LENGTH_SHORT).show();
                blackListIntent = new Intent("com.jason.floating.notification.appPickerFragment.ListViewAdapter");
                blackListIntent.putExtra("packageName", packagesForAdapter[pos].name);
                packagesForAdapter[pos].isChecked = true;
            }else{
                Toast.makeText(context, "Item unchecked: " + pos + " App: " + packagesForAdapter[pos].name, Toast.LENGTH_SHORT).show();
                blackListIntent.removeExtra("packageName");
                packagesForAdapter[pos].isChecked = false;
            }
            context.sendBroadcast(blackListIntent);
            editor.putBoolean("CheckValue" + pos, isChecked);
            editor.commit();
            packagesForAdapter[pos].isChecked = isCheck;
             **/
            packagesForAdapter[position].isChecked = isChecked;
        }
    });

    return convertView;
}

}

You should define a variable called isChecked in your class AppPicker.Package.

So, in your setOnCheckedChangeListener you will store checked state in AppPicker.Package[pos].isChecked

Then, in your getView method:
you will call: viewHolder.checkBox.setChecked(AppPicker.Package[pos].isChecked) // something like this.

There are many ways to do this.

Update: You need a way to find your checkbox for each item in packagesForAdapter. You create it the id, it can be anything unique.

For example, add a counter to packagesForAdapter when you create your data and use that.

String anIdForThisCheckbox = packagesForAdapter[position].id; 

In your getView()

...
final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
boolean isChecked = pref.getBoolean(anIdForThisCheckbox,  false);
viewHolder.checkBox.setChecked(isChecked );
 ...

Create an onClickListener for your checkbox:

viewHolder.checkBox.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        Editor editor = pref.edit();

        if (viewHolder.checkBox.isChecked()) {//Selected
            editor.putBoolean(anIdForThisCheckbox, true);//save state 

        } else {
            editor.putBoolean(anIdForThisCheckbox, false);
        }
    }
    editor.apply/commit
});
...

You add isChecked as a class member of AppPicker.Package.

Then:

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    SharedPreferences sharedPreferences = context.getSharedPreferences("sharedPreferences", Context.MODE_PRIVATE);
    ViewHolder viewHolder;
    LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if(convertView == null) {
        convertView = layoutInflater.inflate(R.layout.list_item, null);
        viewHolder = new ViewHolder();
        viewHolder.text = (TextView) convertView.findViewById(R.id.icon_text);
        viewHolder.icon = (ImageView) convertView.findViewById(R.id.icon_image);
        viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.icon_check);

        convertView.setTag(viewHolder);
    }else{
        viewHolder = (ViewHolder) convertView.getTag();
    }

    editor = sharedPreferences.edit();

    viewHolder.icon.setImageDrawable(packagesForAdapter[position].icon);
    viewHolder.text.setText(packagesForAdapter[position].label);
    viewHolder.checkBox.setChecked(packagesForAdapter[position].isChecked);// add by tauitdnmd
    viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {

            packagesForAdapter[position].isChecked = isChecked; // add by tauitdnmd

        }
    });

    return convertView;
}

Thanks for all you guys' support. But I finally managed to find a solution for such annoying question. Using a Model to store the checkboxes' states, take the value everytime the listview updates and set the checked state of the checkboxes. It took me some time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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