使用自定义列表适配器删除错误的列表项而不是选定的项

时间:2011-11-06 15:42:19

标签: android

我创建了一个带复选框的自定义ListView。我想在“删除”菜单选项选项中删除所选项目。    我在CheckBox上处理onCheckedChanged事件。这里我维护一个ArrayList来记下所选元素的位置。现在,当用户选择“删除”菜单项时,我会从ListAdapter的ArrayList中删除选择的项目。

以下是我的代码,

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    names = new ArrayList<String>();
    names.add("first");
    names.add("second");
    names.add("three");
    names.add("four");
    names.add("five");
    names.add("six");
    names.add("seven");
    names.add("eight");
    names.add("nine");

    listAdapter = new SelfAdapter(this,names);

    this.setListAdapter(listAdapter);                       
}

    @Override
public boolean onOptionsItemSelected(MenuItem menuItem){
    int menuId = menuItem.getItemId();
    ArrayList<Integer> selectedItems;
    switch(menuId){
    case R.id.delitem:
        Log.d(TAG,"del item selected");
        selectedItems = listAdapter.getSelected();
           **//pick the selected position items and delete them from the
           // listadapter arraylist**
        for(Integer element: selectedItems){
          Log.d(TAG,"Selected:"+element.toString());
          names.remove(element.intValue());
          listAdapter.notifyDataSetChanged(); 
        }          
    }
    return true;
}

以下是自定义适配器的代码,

class SelfAdapter extends ArrayAdapter<String>{
ViewHolder holder = new ViewHolder();
private Activity context;
private ArrayList<String> names;
private String TAG = "SelfAdapter"; 
ArrayList<Integer> checkedPos; **//contains the selected items position**
public SelfAdapter(Context context, ArrayList names) {
    super(context,R.layout.checkboxnlist, names);
    this.context = (Activity) context;
    this.names = names;
    checkedPos = new ArrayList<Integer>();
}

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

    final int listPosition = position;

    if(convertView == null){
        LayoutInflater inflater = context.getLayoutInflater();
        convertView = inflater.inflate(R.layout.checkboxnlist,parent,false);            
        holder.chkBox = (CheckBox)convertView.findViewById(R.id.chkvw);
        holder.txtView = (TextView)convertView.findViewById(R.id.txtvw);
        convertView.setTag(holder);
    }
    else{
        holder = (ViewHolder) convertView.getTag();
    }

    holder.txtView.setText(names.get(position));
    holder.chkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            Log.d(TAG,"listPosition:"+listPosition);
          if(isChecked){
              checkedPos.add(new Integer(listPosition));
          }
          else{
              checkedPos.remove(listPosition);
          }
        }
    });
    return convertView;
}

public ArrayList<Integer> getSelected(){
    return checkedPos;
}

static class ViewHolder{
    TextView txtView;
    CheckBox chkBox;
}

}

现在的问题是,如果选择第1个,第2个项目(例如),那么我会看到错误的项目被删除,并且列表视图在完全错误之后填充。稍后,如果我尝试删除它正在抛出“索引越界异常”的项目。我想在getView方法中代码出错了。

有人可以帮助我找出这里的错误。

由于

2 个答案:

答案 0 :(得分:1)

names删除元素时,还需要从checkedPos数组中删除元素。否则,两个数组将具有不同的长度。然后,当您再次尝试时,checkedPos将超过names,并最终导致索引超出范围异常。

此外,当您从names删除时,您无法使用正常的迭代器。如果您应该删除索引1和2处的名称,那么当您删除名称1时,名称2会向上移动到位置1.但您的索引不会相应地更新。最简单的解决方案是向后遍历位置数组,从names的末尾删除,然后从开头删除。

P.S。将序数(“第一”,“第二”)切换到列表中间的基数(“三”,“四”等)有点奇怪。

答案 1 :(得分:0)

你必须删除 names = new ArrayList&lt; STRING&gt;();

但是你删除了selectedItems;