I have a ListView which 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 fairly simple so I won't post them unless anyone thinks they are relevant.
The problem is that some of the CheckBoxes are not responding. It seems to be the ones that are visible when the layout is first displayed. Any that you have to scroll down to work as expected.
Any pointers appreciated.
Your code from the answer works but is inefficient(you can actually see this, just scroll the ListView
and check the Logcat
to see the garbage collector doing it's work). An improved getView
method which will recycle views is the one below:
@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
}
};
Regarding your code from your question, at first I thought it was wrong because of the way you setup the rows but I don't see why the adapter will have that behavior as you detached the row view from the list. Also, I even tested the code and it works quite well regarding CheckBoxes
(but with very poor memory handling). Maybe you're doing something else that makes the adapter to not work?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With