How to save state of CheckBox while scrolling in L

2019-07-16 09:20发布

问题:

I have used ListView with custom adapter, so my ListView includes CheckBox, but problem is that when I scroll down, checked CheckBoxes uncheck, how can I do it with this code?

UPDATE

My custom adapter:

    public class AppsArrayAdapter extends ArrayAdapter<String> {
    private final Context context;

    private List<Integer> checkedItems;

    private final String DefaultApps = "def_apps";

    public AppsArrayAdapter(Context context, String[] values, List<Integer> checkedItems) {//XXX
        super(context, R.layout.apps, values);
        this.context = context;
        this.checkedItems = checkedItems;//XXX
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        SharedPreferences myPrefsApps =context.getSharedPreferences("myPrefsApps", Context.MODE_PRIVATE);
        String prefNameDefaultApps = myPrefsApps.getString(DefaultApps, "");
        String prefNameDefaultAppsVer = myPrefsApps.getString(DefaultAppsVer, "");


        LayoutInflater inflater = (LayoutInflater)context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View rowView = inflater.inflate(R.layout.apps, parent, false);
        TextView text_apps = (TextView)rowView.findViewById(R.id.text_apps);
        CheckBox check = (CheckBox)rowView.findViewById(R.id.check_apps);
        text_apps.setText(prefNameDefaultApps.split("\n")[position]);

        check.setChecked(checkedItems.contains((Integer) position));
        return rowView;
    }   
}

And my Activity:

    public class AppsActivity extends ListActivity {
    private final String DefaultApps = "def_apps";

    private List<Integer> checkedItems = new ArrayList<Integer>();


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        AppsArrayAdapter adapter = new AppsArrayAdapter(this, prefNameDefaultApps.split("\n"), checkedItems);
        setListAdapter(adapter);
}
}
@Override
    public void onListItemClick(ListView l, View v, int position, long id) {
       if(checkedItems.contains((Integer) position)) checkedItems.remove((Integer) position);
       else checkedItems.add((Integer) position);
    }

回答1:

// initialise the list
private List<Integer> selection = new ArrayList<Integer>();

for (String str: prefNameDefaultApps.split("\n")) {
        selection.add(0);
}


// setting the list 
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
        if(CheckBox is checked) {//(check if the checkbox is checked )
               selection.set(position, 1);
        }
        else{
               selection.set(position, 0);
        }
}

// show in the listView
@Override
public View getView(int position, View convertView, ViewGroup parent) {

        ....
        ....
        check.setChecked(selection.get(position) == 0 ? false : true);

}

This should get you going :)



回答2:

I'm not entirely sure whether there is a standard solution in Android, but this should do the trick:

public class AppsArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private List<Integer> checkedItems;//Here we save the position of the selected items.

private final String DefaultApps = "def_apps";
//This will be invoked when one of the CheckBoxes gets clicked. It will update the checkedItems list.
private View.OnClickListener onClickListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Integer position = (Integer) v.getTag();
        if(checkedItems.contains(position)) checkedItems.remove(position);
        else checkedItems.add(position);
    }
};

public AppsArrayAdapter(Context context, String[] values, List<Integer> checkedItems) {//XXX
    super(context, R.layout.apps, values);
    this.context = context;
    this.checkedItems = checkedItems;//XXX
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    SharedPreferences myPrefsApps =context.getSharedPreferences("myPrefsApps", Context.MODE_PRIVATE);
    String prefNameDefaultApps = myPrefsApps.getString(DefaultApps, "");

    //You shouldn't inflate the View everytime getView() is called,
    /*LayoutInflater inflater = (LayoutInflater)context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    View rowView = inflater.inflate(R.layout.apps, parent, false);*/
    //rather let the superclass handle it as it's more efficient.
    View rowView = super.getView(position, convertView, parent);

    TextView text_apps = (TextView)rowView.findViewById(R.id.text_apps);
    CheckBox check = (CheckBox)rowView.findViewById(R.id.check_apps);
    text_apps.setText(prefNameDefaultApps.split("\n")[position]);

    check.setChecked(checkedItems.contains((Integer) position));//XXX
    check.setTag((Integer) position);//XXX
    check.setOnClickListener(onClickListener);//XXX
    return rowView;
}   

}

In your ListActivity, add a field private List<Integer> checkedItems = new ArrayList<Integer>;. You have to pass this List in the Adapter constructor!
If you want to check whether the nth item in your ListView was selected, just look whether n is saved in checkedItems, i.e.

if(checkedItems.contains(requestedItemPosition)) {
    //Item was selected.
} else {
    //Item was not selected.
}

I really recommend you not to inflate the views by yourself.



回答3:

Try this: (your custom adapter)

 public class AppsArrayAdapter extends ArrayAdapter<String> {
private final Context context;

private List<Integer> checkedItems;

private final String DefaultApps = "def_apps";
LayoutInflater inflater;

public AppsArrayAdapter(Context context, String[] values, List<Integer> checkedItems) {//XXX
    super(context, R.layout.apps, values);
    this.context = context;
    this.checkedItems = checkedItems;//XXX
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    SharedPreferences myPrefsApps =context.getSharedPreferences("myPrefsApps", Context.MODE_PRIVATE);
    String prefNameDefaultApps = myPrefsApps.getString(DefaultApps, "");
    String prefNameDefaultAppsVer = myPrefsApps.getString(DefaultAppsVer, "");


View rowView = convertView;
ViewHolder viewH = new ViewHolder();

if ( rowView == null){
        rowView = inflater.inflate(R.layout.apps, parent, false);
        viewH.text_apps = (TextView)rowView.findViewById(R.id.text_apps);
        viewH.check = (CheckBox)rowView.findViewById(R.id.check_apps);
    rowView.setTag(viewH);
}else{
    viewH = (ViewHolder) rowView.getTag();
}

    viewH.text_apps.setText(prefNameDefaultApps.split("\n")[position]);
    viewH.check.setChecked(checkedItems.contains((Integer) position));

    return rowView;
}   

static class ViewHolder {
    public TextView text_apps;
    public CheckBox check;  

}

}

Hope this helps :)



回答4:

you should use MyAdapter newad=(MyAdapter)adapter.getAdapter(); newad.notifyDataSetChanged(); this code in onitem click method and MyAdapter is class of Adapter and make new object like this one and in adapter class you should have to write a line

LayoutInflater in; in=(LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); in adapter constructor simple