How to check all checkboxes in a ListView

情到浓时终转凉″ 提交于 2019-12-23 05:31:02

问题


I have a list, in which each row contains a checkbox and a textview, also I have a button which should check/uncheck all checkboxes in the list, however, I have not been able to achieve this with the checkboxes OUTSIDE of the screen, only with the visibles one. And if I understood well, that happens because items outside of the screens dont exist, they are recycled to create the new rows while scrolling, causing null pointers/out of index errores while trying to check/access the checkboxes outside of the screen.

I Googled for solutions but nothing worked so far.

How can I solve this?

Here is the adapter:

public class AlumnoArrayAdapter<T> extends BaseAdapter{

    Context mContext;
    LayoutInflater mInflater;
    ArrayList<T> mList;
    ArrayList<Alumno> alumno;
    boolean verEstadisticas;
    SparseBooleanArray mSparseBooleanArray;

    public AlumnoArrayAdapter(Context context, ArrayList<T> list, ArrayList<Alumno> alumno, boolean verEstadisticas) {

        //TODO Auto-generated constructor stub
        this.alumno = alumno;
        this.verEstadisticas = verEstadisticas;

        this.mContext = context;

        mInflater = LayoutInflater.from(mContext);
        mSparseBooleanArray = new SparseBooleanArray();
        mList = new ArrayList<T>();
        this.mList = list;
    }

    public ArrayList<T> getCheckedItems() {
        ArrayList<T> mTempArry = new ArrayList<T>();

        for(int i=0;i<mList.size();i++) {
            if(mSparseBooleanArray.get(i)) {
                mTempArry.add(mList.get(i));
            }
        }
        return mTempArry;
    }

    public int getCount() {
        return mList.size();
    }

    public Object getItem(int position) {
        return mList.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(final int position, View convertView, ViewGroup parent) {       

        if(convertView == null) {
            convertView = mInflater.inflate(R.layout.row, null);
        }

        TextView tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);
        tvTitle.setText(mList.get(position).toString());

        CheckBox mCheckBox = (CheckBox) convertView.findViewById(R.id.chkEnable);
        mCheckBox.setTag((Integer) position);
        mCheckBox.setChecked(mSparseBooleanArray.get(position));
        mCheckBox.setOnCheckedChangeListener(mCheckedChangeListener);

        if(verEstadisticas){
            mCheckBox.setVisibility(View.GONE);
        }   

        mCheckBox.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                CheckBox cb = (CheckBox) v;
                Integer position = (Integer) cb.getTag();
                alumno.get(position).setChecked(cb.isChecked());                
            }
        });     

        return convertView;
    }

    OnCheckedChangeListener mCheckedChangeListener = new OnCheckedChangeListener() {

        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {            
            mSparseBooleanArray.put((Integer) buttonView.getTag(), isChecked);          
        }
    };
}

If more code is needed please let me know.

Would appreciate any help possible.

Thanks in advance!

EDIT: Got a solution!, the modified adapter:

public class AlumnoArrayAdapter<T> extends BaseAdapter{

    Context mContext;
    LayoutInflater mInflater;
    ArrayList<T> mList;
    ArrayList<Alumno> alumno;
    boolean verEstadisticas;
    SparseBooleanArray mSparseBooleanArray;

    boolean checarTodo = false;

    public AlumnoArrayAdapter(Context context, ArrayList<T> list, ArrayList<Alumno> alumno, boolean verEstadisticas) {

        //TODO Auto-generated constructor stub
        this.alumno = alumno;
        this.verEstadisticas = verEstadisticas;

        this.mContext = context;

        mInflater = LayoutInflater.from(mContext);
        mSparseBooleanArray = new SparseBooleanArray();
        mList = new ArrayList<T>();
        this.mList = list;
    }

    public ArrayList<T> getCheckedItems() {
        ArrayList<T> mTempArry = new ArrayList<T>();

        for(int i=0;i<mList.size();i++) {
            if(mSparseBooleanArray.get(i)) {
                mTempArry.add(mList.get(i));
            }
        }
        return mTempArry;
    }

    public int getCount() {
        return mList.size();
    }

    public Object getItem(int position) {
        return mList.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public void checkAll(){
        for(int x = 0; x < alumno.size(); x++){
            alumno.get(x).setChecked(!alumno.get(x).isChecked());
        }
    }

    public View getView(final int position, View convertView, ViewGroup parent) {       

        if(convertView == null) {
            convertView = mInflater.inflate(R.layout.row, null);
        }

        TextView tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);
        tvTitle.setText(mList.get(position).toString());

        CheckBox mCheckBox = (CheckBox) convertView.findViewById(R.id.chkEnable);
        mCheckBox.setTag((Integer) position);
        mCheckBox.setChecked(alumno.get(position).isChecked());

        if(verEstadisticas){
            mCheckBox.setVisibility(View.GONE);
        }   

        mCheckBox.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                CheckBox cb = (CheckBox) v;
                //Alumno Alumno = (Alumno) cb.getTag();
                Integer position = (Integer) cb.getTag();
                alumno.get(position).setChecked(cb.isChecked());                
            }
        });     

        return convertView;
    }


}

回答1:


You can try following:

  1. Add one boolean property in adapter and a method to set the same.
  2. On click of button where you want to check all the checkbox. Call the adapter method to set boolean value. And call notifyDataSetChanged, this should invalidate and redraw the list view.
  3. While redrawing process, getView method of adapter is called. So in this method check if boolean value is set to true or false and accordingly check or uncheck the check box.

I hope this steps help.




回答2:


You need to manipulate the "checked" information in your underlying data structure. As you correctly say, the GUI objects only serve the purpose of representing a visual form to your underlying data. It's tempting, but not such a good idea to use GUI objects as the only means to hold application status information.




回答3:


Check this code. Try to adopt to your adapter. It is not the same. But little modification will definitely work.

class CustomAdapter extends ArrayAdapter<ContactPerson>{
        private ArrayList<ContactPerson> contactList;

        public CustomAdapter(Context context, int textViewResourceId,
                ArrayList<ContactPerson> contactList) {
            super(context, textViewResourceId, contactList);
            // TODO Auto-generated constructor stub
            this.contactList = new ArrayList<ContactPerson>();
            this.contactList.addAll(contactList);
        }

        private class ViewHolder{
            TextView ContactName;
            CheckBox contactCheck;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub

            ViewHolder holder = null;
            Log.v("Convert View", String.valueOf(position));

            if(convertView==null){
                LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

                convertView = inflater.inflate(R.layout.checkbox_item, null);

                holder = new ViewHolder();
                holder.ContactName = (TextView) convertView.findViewById(R.id.contact_name);
                holder.contactCheck = (CheckBox) convertView.findViewById(R.id.contact_check);

                convertView.setTag(holder);

                holder.contactCheck.setOnClickListener(new View.OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        CheckBox cb = (CheckBox) v;
                        ContactPerson contact = (ContactPerson) cb.getTag();
//                      Log.i("clicked users", contact.getName());

                        contact.setSelected(cb.isChecked());
                    }
                });
            }
            else{
                holder = (ViewHolder) convertView.getTag();
            }

            ContactPerson contacts = contactList.get(position);
            holder.ContactName.setText("("+contacts.getName()+")");
            holder.contactCheck.setChecked(contacts.isSelected());
            holder.contactCheck.setTag(contacts);
            holder.ContactName.setText(contacts.getName());
            return convertView;
        }
    }



    private void checkButtonClick(){
        Button nextButton = (Button) findViewById(R.id.selected_done);
        nextButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                StringBuffer display = new StringBuffer();
                display.append("the selected contacts are");

                ArrayList<ContactPerson> finalContactList = contactAdapter.contactList;
                for(int i=0;i<finalContactList.size();i++){
                    ContactPerson selected = finalContactList.get(i);
                    if(selected.isSelected()){
                        display.append("\n"+selected.getName()+"\t"+selected.getPhoneNumber());
                    }
                }
                Toast.makeText(getApplicationContext(), display, Toast.LENGTH_LONG).show();
            }
        });
    }



回答4:


I would use the built-in listview function for marking items checked: setItemChecked, combined with a custom checkable view for the rows. For an excellent walkthrough on creating a checkable view (with a section on handling checkbox children) see Here. For completeness, here is an example of a checkable view:

public class ExampleListItemView extends RelativeLayout implements Checkable {

    private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked };

    public ExampleListItemView(Context context) {
            super(context);
    }

    public ExampleListItemView(Context context, AttributeSet attrs) {
            super(context, attrs);
    }

    public ExampleListItemView(Context context, AttributeSet attrs,
                    int defStyle) {
            super(context, attrs, defStyle);
    }

    TextView txtExample;
    CheckBox cbExample;

    private boolean isChecked = false;

    @Override
    protected void onFinishInflate() {
            super.onFinishInflate();        
            txtExample = (TextView) findViewById(R.id.txtExample);
            cbExample = (CheckBox) findViewById(R.id.cbExample);
            isChecked = false;
    }

    public void setText(String text){
            txtExample.setText(text);
    }

    @Override
    public boolean isChecked() {
            return isChecked;
    }

    @Override
    public void setChecked(boolean checked) {                

            if (isChecked != checked) {
                    cbExample.setChecked(checked);
                    isChecked = checked;
                    refreshDrawableState();
            }
    }

    @Override
    public void toggle() {
            setChecked(!isChecked);
    }

    @Override
    public int[] onCreateDrawableState(int extraSpace) {
            final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
            if (isChecked()) {
                    mergeDrawableStates(drawableState, CHECKED_STATE_SET);
            }
            return drawableState;
    }

And the associated xml layout:

<?xml version="1.0" encoding="utf-8"?>
<com.example.ExampleListItemView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    ndroid:addStatesFromChildren="true" >

    <CheckBox android:id="@+id/cbExample" />

    <TextView
        android:id="@+id/txtExample"
        android:layout_toRightOf="@id/cbExample" />

</com.example.ExampleListItemView>

You would then end up with something like this:

for(int i = 0; i < adapter.getCount(); i++){
    listView.setItemChecked(i, true);
}

SparseBooleanArray checked = listView.getCheckedItemPositions();


来源:https://stackoverflow.com/questions/20489901/how-to-check-all-checkboxes-in-a-listview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!