Listview with custom adapter containing CheckBoxes

I have a ListView that uses a custom adapter, as shown:

private class CBAdapter extends BaseAdapter implements OnCheckedChangeListener{ Context context; public String[] englishNames; LayoutInflater inflater; CheckBox[] checkBoxArray; LinearLayout[] viewArray; private boolean[] checked; public CBAdapter(Context con, String[] engNames){ context=con; englishNames=engNames; inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); checked= new boolean[englishNames.length]; for(int i=0; i<checked.length; i++){ checked[i]=false; //Toast.makeText(con, checked.toString(),Toast.LENGTH_SHORT).show(); } checkBoxArray = new CheckBox[checked.length]; viewArray = new LinearLayout[checked.length]; } public int getCount() { return englishNames.length; } public Object getItem(int position) { // TODO Auto-generated method stub return null; } public long getItemId(int position) { // TODO Auto-generated method stub return 0; } public View getView(int position, View convertView, ViewGroup parent) { if(viewArray[position] == null){ viewArray[position]=(LinearLayout)inflater.inflate(R.layout.record_view_start,null); TextView tv=(TextView)viewArray[position].findViewById(R.id.engName); tv.setText(englishNames[position]); checkBoxArray[position]=(CheckBox)viewArray[position].findViewById(R.id.checkBox1); } checkBoxArray[position].setChecked(checked[position]); checkBoxArray[position].setOnCheckedChangeListener(this); return viewArray[position]; } public void checkAll(boolean areChecked){ for(int i=0; i<checked.length; i++){ checked[i]=areChecked; if(checkBoxArray[i] != null) checkBoxArray[i].setChecked(areChecked); } notifyDataSetChanged(); } public void onCheckedChanged(CompoundButton cb, boolean isChecked) { for(int i=0; i<checked.length; i++){ if(cb == checkBoxArray[i]) checked[i]=isChecked; } } public boolean itemIsChecked(int i){ return checked[i]; } } 

The layouts are pretty simple, so I won’t post them unless someone considers them relevant.

The problem is that some of the CheckBox are not responding. They seem to be visible when the layout is first displayed. Anything you need to scroll down to work as expected.

Any pointers appreciated.

+8
java android checkbox listview adapter
source share
3 answers

Your code from the answer works, but is inefficient (you can see it, just scroll through the ListView and check Logcat to see how the garbage collector does this while working). The improved getView method that will handle the views is as follows:

 @Override public View getView(int position, View convertView, ViewGroup parent) { LinearLayout view = (LinearLayout) convertView; if (view == null) { view = (LinearLayout) inflater.inflate(R.layout.record_view_start, parent, false); } TextView tv = (TextView) view.findViewById(R.id.engName); tv.setText(getItem(position)); CheckBox cBox = (CheckBox) view.findViewById(R.id.checkBox1); cBox.setTag(Integer.valueOf(position)); // set the tag so we can identify the correct row in the listener cBox.setChecked(mChecked[position]); // set the status as we stored it cBox.setOnCheckedChangeListener(mListener); // set the listener return view; } OnCheckedChangeListener mListener = new OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { mChecked[(Integer)buttonView.getTag()] = isChecked; // get the tag so we know the row and store the status } }; 

As for your code from your question, at first I thought it was wrong, because of how you configure the strings, but I don’t understand why the adapter will have this behavior, since you separated the presentation of the string from the list. In addition, I even tested the code, and it works pretty well regarding CheckBoxes (but with very poor memory handling). Maybe you are doing something else that makes the adapter not work?

+15
source share

Let me first say that you have chosen one of the main advantages of using an adapter: reusable views. Keeping a hard link to every created View has a high risk of getting to the memory ceiling. You must reuse convertView when it is not NULL, and create your view when convertView is null. There are many tutorials that show you how to do this.

The views used in the adapter usually have an OnClickListener attached to them by the parent View , so you can set OnItemClickListener to the ListView . This will cause any viewers to relate to individual views. Try setting android:clickable="true" in the CheckBox in XML.

+1
source share

This may not be the most elegant or effective solution, but it works for my situation. For some reason, trying to reuse views either from an array of views or using convertView does just about anything, and the beatbox doesn't respond.

The only thing that worked was to create a new view every time getView () was called.

  public View getView(final int position, View convertView, ViewGroup parent) { LinearLayout view; view=(LinearLayout)inflater.inflate(R.layout.record_view_start,null); TextView tv=(TextView)view.findViewById(R.id.engName); tv.setText(englishNames[position]); CheckBox cBox=(CheckBox)view.findViewById(R.id.checkBox1); cBox.setChecked(checked[position]); cBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { checked[position]=isChecked; } }); return view; } 

The search for this solution was also made difficult by the fact that I called a separately defined onCheckedChangedListener, which then determined which CheckBox by id, instead of having a new listener for each CheckBox.

So far, I have not noted this as the correct answer, as I hope that others may have some contribution to the relatively wasteful restructuring of the view each time.

0
source share

All Articles