![](/img/trans.png)
[英]Using OnItemClickListener on CheckBoxes in ListView with Adapter
[英]Listview with custom adapter containing CheckBoxes
我有一個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創建一個新的偵聽器,因此查找此解決方案也受到了阻礙。
到目前為止,我還沒有將此標記為正確的答案,因為我希望其他人可能會對每次重建視圖相當浪費。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.