Android 在长列表视图中选择特定复选框将选中多个复选框

Android 在长列表视图中选择特定复选框将选中多个复选框,android,listview,checkbox,Android,Listview,Checkbox,我有一个带有复选框的列表视图。我单击特定的项目,相应的复选框被选中,但它也会在listview中每隔8-10行重复选择复选框。我理解这种情况发生的原因是,在android中,只存储可见屏幕的视图以优化内存。但我没有能够克服这种情况。请建议 public class FBFriendsListAdaptor extends ArrayAdapter<FBFriendItem>{ private final Context context; private stati

我有一个带有复选框的列表视图。我单击特定的项目,相应的复选框被选中,但它也会在listview中每隔8-10行重复选择复选框。我理解这种情况发生的原因是,在android中,只存储可见屏幕的视图以优化内存。但我没有能够克服这种情况。请建议

public class FBFriendsListAdaptor extends ArrayAdapter<FBFriendItem>{
     private final Context context;
     private static List<FBFriendItem> items;
     private SparseArray<FBFriendItem> checkedItems = new SparseArray<FBFriendItem>();
     ViewHolder holder;

     public FBFriendsListAdaptor(Context context, List<FBFriendItem> items) {
         super(context, R.layout.fb_friend_list, items);
         this.items = items;
         this.context = context;
     }

     @Override
     public FBFriendItem getItem(int position) {
        // TODO Auto-generated method stub
        return items.get(position);
     }

     public View getView(final int position, View convertView, ViewGroup parent) {

         View v = convertView;

         if (v == null) {
             LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             v = vi.inflate(R.layout.fb_friend_list, parent, false);
         }

         holder = new ViewHolder();
         holder.selectFriendCB = (CheckBox)v.findViewById(R.id.selectFriendCB);
         v.setTag(holder);

         v.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v) {
                if (checkedItems.get(position) != null){
                    checkedItems.remove(position);
                    holder.selectFriendCB.setChecked(false);
                }
                else {
                    checkedItems.put(position, items.get(position));
                    holder.selectFriendCB.setChecked(true);
                }
            }
         });

         FBFriendItem item = items.get(position);
         TextView firstNameTV = (TextView) v.findViewById(R.id.firstNameTV);
         TextView lastNameTV = (TextView) v.findViewById(R.id.lastNameTV);
         ImageView picIV = (ImageView) v.findViewById(R.id.picIV);
         if (!item.getFbId().isEmpty()) {
             firstNameTV.setText(" " + item.getFirstName());
             lastNameTV.setText(" " + item.getLastName());
             Bitmap image = item.getImage();
             if(image != null) {
                 picIV.setImageBitmap(image);
             }
         }

         return v;
     }

     public SparseArray<FBFriendItem> getCheckedItems(){
         return checkedItems;
     }

     static class ViewHolder {
         CheckBox selectFriendCB;        
     }
}
公共类FBFriendsListAdapter扩展了ArrayAdapter{
私人最终语境;
私有静态列表项;
私有SparseArray checkedItems=新SparseArray();
视窗座;
公共FBFriendsListAdaptor(上下文、列表项){
超级(上下文、R.layout.fb\u好友列表、项目);
这个项目=项目;
this.context=上下文;
}
@凌驾
公共FBFriendItem getItem(内部位置){
//TODO自动生成的方法存根
返回项目。获取(位置);
}
公共视图getView(最终整数位置、视图转换视图、视图组父视图){
视图v=转换视图;
如果(v==null){
LayoutInflater vi=(LayoutInflater)context.getSystemService(context.LAYOUT\u INFLATER\u SERVICE);
v=vi.充气(R.layout.fb\u friend\u list,父项,false);
}
holder=新的ViewHolder();
holder.selectFriendCB=(复选框)v.findViewById(R.id.selectFriendCB);
v、 setTag(支架);
v、 setOnClickListener(新视图。OnClickListener(){
公共void onClick(视图v){
if(checkedItems.get(位置)!=null){
检查EditEMS。移除(位置);
holder.selectFriendCB.setChecked(false);
}
否则{
checkedItems.put(位置,items.get(位置));
holder.selectFriendCB.setChecked(true);
}
}
});
FBFriendItem=items.get(位置);
TextView firstNameTV=(TextView)v.findViewById(R.id.firstNameTV);
TextView lastNameTV=(TextView)v.findViewById(R.id.lastNameTV);
ImageView picIV=(ImageView)v.findViewById(R.id.picIV);
如果(!item.getFbId().isEmpty()){
firstNameTV.setText(“+item.getFirstName());
lastNameTV.setText(“+item.getLastName());
位图图像=item.getImage();
如果(图像!=null){
picIV.setImageBitmap(图像);
}
}
返回v;
}
公共SparseArray getCheckedItems(){
返回支票;
}
静态类视窗夹{
复选框选择Friendcb;
}
}

我注意到的第一件事是

     if (!item.getFbId().isEmpty()) {
         firstNameTV.setText(" " + item.getFirstName());
         lastNameTV.setText(" " + item.getLastName());
         Bitmap image = item.getImage();
         if(image != null) {
             picIV.setImageBitmap(image);
         }
     }
仅在某些情况下设置这些值是一个很大的禁忌。请记住,您的视图正在被重用,因此,如果您设置了这些属性中的任何一个,就不能指望它们具有默认值。它们可能仍然是从最后一项设置的。请尝试以下类似的逻辑:

     if (!item.getFbId().isEmpty()) {
         firstNameTV.setText(" " + item.getFirstName());
         lastNameTV.setText(" " + item.getLastName());
         Bitmap image = item.getImage();
         if(image == null) {
             // reset the default because this view might have last displayed an
             // item with a non-default value
             picIV.setImageBitmap(myDefaultImage);
         } else {
             picIV.setImageBitmap(image);
         }
     } else {
         // reset the defaults because this view might have last displayed an
         // item with a non-default value
         firstNameTV.setText(null);
         lastNameTV.setText(null);
         picIV.setImageBitmap(myDefaultImage);
     }

我注意到的下一件事是,您对检查项目的管理是完全错误的。项目是否被选中是应该由
列表视图管理的状态,而不是适配器管理的状态。我不知道您想要实现什么样的外观,因此我不打算具体说明如何布置项目,但您可能希望从删除
复选框
元素开始,并查看
ListView.setChoiceMode()

这就是它的工作原理。我向FBFriendItem类添加了一个“boolean selected=false”。 以下是阵列适配器内部的getView()代码:

public View getView(final int position, View convertView, ViewGroup parent) {

     ViewHolder holder = null;

     View v = convertView;
     if (v == null) {
         LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         v = vi.inflate(R.layout.fb_friend_list, null);
         holder = new ViewHolder();
         holder.picIV = (ImageView)v.findViewById(R.id.picIV);
         holder.firstNameTV = (TextView)v.findViewById(R.id.firstNameTV);
         holder.lastNameTV = (TextView)v.findViewById(R.id.lastNameTV);
         holder.selectFriendCB = (CheckBox)v.findViewById(R.id.selectFriendCB);
         v.setTag(holder);
         holder.selectFriendCB.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v) {
                CheckBox cb = (CheckBox)v;
                FBFriendItem item = (FBFriendItem)cb.getTag();
                item.setSelected(cb.isChecked());
            }
         });
     }
     else {
         holder = (ViewHolder)v.getTag();
     }

     FBFriendItem item = items.get(position);
     holder.picIV.setImageBitmap(item.getImageBitmap());
     holder.firstNameTV.setText(item.getFirstName());
     holder.lastNameTV.setText(item.getLastName());
     holder.selectFriendCB.setChecked(item.isSelected());
     holder.selectFriendCB.setTag(item);

     return v;
 }

 private class ViewHolder {
     ImageView picIV;
     TextView firstNameTV;
     TextView lastNameTV;
     CheckBox selectFriendCB;        
 }

谢谢你的回复。但主要的问题是,当我在listview中选择一个复选框时,它会选择多个条目,即使我删除了上面设置名字和姓氏的代码。e、 g.listview中显示了100个项目,我选中了第2个项目,这样做会自动分别选中所有第13、24、35个项目。我想避免这种情况。即使我在listview本身上添加了一个侦听器,该场景仍然存在。请对此发表评论。正如我提到的,你们所有的支票管理都是错误的。它永远不会像你尝试的那样工作。您需要删除
复选框
小部件并使用
ListView.setChoiceMode()