简体   繁体   中英

android : checkboxes in a ListView ( strange behaviour of selected element)

I found here and here similar issues, but the problem is slightly different.

In a ListView, I try to put an adapter (extends from base Adapter) which contents checkbox.

List view layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/mainLayout"
 >

    <Button
        android:id="@+id/close_cat"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="buttonClick"
        android:text="@string/back" />

    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>

XML of list's elements:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <TableLayout
        android:id="@+id/blocCheck"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="25px"
        android:layout_marginTop="25px"
        android:background="@color/black" >

        <TableRow
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:baselineAligned="true"
            android:paddingLeft="4sp" >

            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:layout_weight="1"
                android:orientation="horizontal"
                android:paddingLeft="20sp" >

                <ImageView
                    android:id="@+id/iv_cat"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />

                <TextView
                    android:id="@+id/category"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="left"
                    android:layout_marginLeft="15dip"
                    android:text="tfgldkjhglf"
                    android:textSize="20sp" />
            </LinearLayout>

            <CheckBox
                android:id="@+id/check_cat"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right"
                android:layout_marginRight="10sp"
                android:onClick="MyHandler" />
        </TableRow>
    </TableLayout>

</LinearLayout>

I set adapter in my view :

list = getListView();
list.setAdapter(new CatAdapter(this, listCat));

My adapter:

public class CatAdapter extends BaseAdapter {

    private LayoutInflater  mInflater;
    private List<CatAdapterObject> mListAppInfo;
    private Context mContext;


    /**
     * Constructor
     * @param context
     * @param data
     * @param resource
     * @param from
     * @param to
     */
    public CatAdapter (Context context, List<CatAdapterObject> list){   
        mContext = context;
        mListAppInfo = list;
        mInflater = LayoutInflater.from(mContext);      
    }

    /**
     * number of elements
     */
    @Override
    public int getCount() {
        return mListAppInfo.size();
    }

    /**
     * get an item in the list
     */
    @Override
    public Object getItem (int position){
        return mListAppInfo.get(position).getId();
    }

    /**
     * get id of the selected item
     */
    @Override
    public long getItemId(int position) {
        return mListAppInfo.get(position).getId();
    }

    /**
     * get the view
     */
    @Override
    public View getView (int position, View convertView, ViewGroup parent){

        LinearLayout layoutItem;

        if (convertView == null) {
            layoutItem = (LinearLayout) mInflater.inflate(R.layout.category,    parent, false);
        } else {
            layoutItem = (LinearLayout) convertView;
        }

        // get the current category
        CatAdapterObject entry =  mListAppInfo.get(position);

        //view setting
        TextView category = (TextView) layoutItem.findViewById(R.id.category);
        CheckBox cb         = (CheckBox) layoutItem.findViewById(R.id.check_cat);
        ImageView iv_cat    = (ImageView) layoutItem.findViewById(R.id.iv_cat);

        //elements setting
        category.setText(entry.getName());

        //checkbox
        cb.setChecked(entry.isChecked());
        cb.setTag(position);

        //picture
        Bitmap icon = Utils.getResizedBitmap(BitmapFactory.decodeResource(mContext.getResources(),entry.getPict()),45,45,true);     
        iv_cat.setImageBitmap(icon);

        return layoutItem;

    }
}

When activity is lauched, list is displayed perfectly. I can scroll up/down without any problem. However, when I check one of the checkboxes and scroll down, box which was checked "loose" its check mark and the background color of the latest box in the list changed.

When checking a box, below method is called (In my activity file):

public void MyHandler(View v) {

        //クリックされたcheckbox
        cb = (CheckBox) v;

        Log.d("CHECKBOX","before :"+Utils.implode(",",this.cat_id_list));

        //get position in the list
        Integer position = Integer.parseInt(cb.getTag().toString());

        //instance of the view (list's child)
        View o = list.getChildAt(position).findViewById(R.id.blocCheck);

        // check if box is checked
        if (cb.isChecked()) { 
            o.setBackgroundResource(R.color.pink);

            this.cat_id_list.add(position.toString());

        // 背景色を替え、リストから削除
        } else { 

            o.setBackgroundResource(R.color.black);

            Collections.sort(this.cat_id_list);
            int index = Collections.binarySearch(this.cat_id_list,position.toString());
            this.cat_id_list.remove(index);

        }

        Log.d("CHECKBOX","after :"+Utils.implode(",",this.cat_id_list));
    }

There are 8 elements in my list but when I check the "mChildrenCount" of the list, there are only 5 elements.

I just want to save in the "this.cat_id_list" id of elements wich were checked and change background color of selected item.

I would appreciate your help !

In your getView you have to something like this (this code is give you an idea how it will work in your case):

ListView lv = ((ListActivity)context).getListView();
// Containing all check states
SparseBooleanArray sba = lv.getCheckedItemPositions();

CheckBox cb = (CheckBox) convertView.findViewById(R.id.yourcheckbox);

cb.setChecked(false);

if(sba != null)
  if(sba.get(position))
     cb.setChecked(true);

That said this what you need on the Activity side.

You have make your ListView to multi-selection mode by android:choiceMode in xml or using setChoiceMode. You check box should be non-clickable and non-focusable.

You have to remove your onClick listener on buttons. Whatever you doing in onClick of button, you have to add that logic to the onListItemClick of ListActivtiy.

I too had the same problem. I solved it using the following method.
I created a bean class to set the checked property of checkbox and used ArrayAdapter . The ArrayAdpater extends the bean class.

Bean Class

public class MCSSCheckState
{
    private boolean isChecked;
    public boolean getIsChecked()
    {
        return isChecked;
    }
    public void setIsChecked(boolean isChecked)
    {
        this.isChecked = isChecked;
    }
}

Java Class

ArrayList<MCSSCheckState> mTitleList = new ArrayList<MCSSCheckState>();
MCSSCheckState check_state=new MCSSCheckState();
check_state.setIsChecked(false);
mTitleList.add(i, check_state);
ListAdapters adapter = new ListAdapters(this,R.id.camTitleTextView, mTitleList);
ListView mListView = (ListView) findViewById(R.id.cameraListView);
mListView.setAdapter(adapter);

Adapter Class

private class ListAdapters extends ArrayAdapter<MCSSCheckState>
{
    private ArrayList<MCSSCheckState> items;
    private int position;       
    public ListAdapters(Context context, int textViewResourceId,
                        ArrayList<MCSSCheckState> mTitleList) 
                        {
                            super(context, textViewResourceId, mTitleList);
                            this.items = mTitleList;
                        }
                        @Override
                        public View getView(int position, View convertView, ViewGroup parent)
                        {
                            View v = convertView;
                            this.position = position;
                            if (v == null)
                            {
                                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                                v = inflater.inflate(R.layout.camerslistinflater, null);
                            }
                            MCSSCheckState o = (MCSSCheckState) items.get(position);
                            if (o != null)
                            {
                                checkBox = (CheckBox) v.findViewById(R.id.checkBox1);
                                checkBox.setTag(position);
                                checkBox.setChecked(o.getIsChecked());
                                checkBox.setOnClickListener(new OnClickListener()
                                {
                                     @Override
                                     public void onClick(View v)
                                     {
                                         MCSSCheckState obj = (MCSSCheckState) items.get(Integer.parseInt(v.getTag().toString()));
                                         obj.setIsChecked(((CheckBox)v).isChecked());
                                         items.set(Integer.parseInt(v.getTag().toString()), obj);                       
                                     }
                                 });
                             }
                             return v;
                         });
}

Hope this helps you.

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