包含CheckBoxes的自定义适配器的Listview

我有一个ListView,它使用自定义适配器,如下所示:

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]; } } 

布局相当简单,所以我不会发布它们,除非有人认为它们是相关的。

问题是一些CheckBox没有响应。 它似乎是首次显示布局时可见的那些。 任何你必须向下滚动按预期工作。

任何指针赞赏。

您的答案中的代码有效,但效率低下(您实际上可以看到这一点,只需滚动ListView并检查Logcat以查看垃圾收集器是否正常工作)。 一个改进的getView方法将回收视图如下:

 @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 } }; 

关于你的问题的代码,起初我认为这是错误的,因为你设置行的方式,但我不明白为什么适配器将具有该行为,因为你从列表中分离行视图。 此外,我甚至测试了代码,它在CheckBoxes工作得很好(但内存处理非常糟糕)。 也许你正在做其他让适配器不能工作的东西?

我首先要说的是,您已经抛弃了使用适配器的一个主要好处:可重用的视图。 对每个创建的View保持一个硬引用会很有可能达到内存上限。 当convertView为非null时,您应该重用convertView ,并在convertView为null时创建视图。 有很多教程可以告诉你如何做到这一点。

适配器中使用的视图通常具有由父View附加到它们的OnClickListener ,以便您可以在ListView上设置OnItemClickListener 。 这将取代个人观点上的任何触摸听众。 尝试在XML中的CheckBox上设置android:clickable="true"

这可能不是最优雅或最有效的解决方案,但它适用于我的情况。 出于某种原因,尝试从视图数组或使用convertView重用视图会使每个事情变得不稳定并且CheckBoxes无法响应。

唯一有效的方法是每次调用getView()时创建一个新的View。

  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; } 

我正在调用一个单独定义的onCheckedChangedListener,然后通过id识别哪个CheckBox,而不是为每个CheckBox创建一个新的侦听器,这也阻碍了find这个解决方案。

到目前为止,我还没有将此标记为正确的答案,因为我希望其他人可能会有一些关于每次都浪费重建视图的意见。