2013-10-07 237 views
0

我一直在使用ListView与每个项目一个CheckableLinearLayout保存复选框状态

CheckableLinearLayout

我不能在ListView检查任何行定义的,它甚至不登记检查用户界面。我不相信CheckableLinearLayoutandroid:checkMark。将CheckedTextView嵌套在我的CheckableLinearLayout中是否正确,如果我使用CheckBox代替,它会更好。另外,如何在检查后立即将它们放入ArrayList,而不是以这种方式迭代它们。

这是我的布局:

<com.example.deltest.CheckableLinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
> 
<CheckedTextView 
android:id="@android:id/text1" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:gravity="center_vertical" 
android:checkMark="?android:attr/listChoiceIndicatorMultiple" 
/> 
<TextView android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:id="@+id/txt_a" 
      /> 
<TextView android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:id="@+id/txt_b" 
    /> 

    </com.example.deltest.CheckableLinearLayout> 

我已经实现了listActivity如下:

public class DeleteList extends ListActivity 
    { 
    ArrayList<Integer> idList=new ArrayList<Integer>(); 
    Cursor c; 
    Handler handler; 
    static final int WHAT=0; 
    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
    super.onCreate(savedInstanceState); 
    final TumblrDB db=new TumblrDB(this); 
    c=db.query(); 
    startManagingCursor(c); 
    handler=new Handler(); 
    View v=getLayoutInflater().inflate(R.layout.layout_header, null,false); 
    getListView().addHeaderView(v); 
    getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 
    SimpleCursorAdapter adapter=new SimpleCursorAdapter(this,R.layout.layout_del,c,new String[] {TumblrDB.DATE,TumblrDB.DESC},new int[]{R.id.txt_a,R.id.txt_b}); 
    getListView().setAdapter(adapter); 
    if(handler.hasMessages(WHAT)) 
    { 
     c=db.query(); 
     ((SimpleCursorAdapter)getListView().getAdapter()).swapCursor(c); 
    } 

    Button btn_del=(Button)v.findViewById(R.id.btn_del); 
    btn_del.setOnClickListener(new OnClickListener(){ 

     @Override 
     public void onClick(View view) { 
      // TODO Auto-generated method stub 
      int count=getListView().getCount(); 
      SparseBooleanArray sparseBooleanArray=getListView().getCheckedItemPositions(); 
      for(int i=0;i<count;i++) 
      { 
       if(sparseBooleanArray.get(i)) 
       { 
        c.moveToPosition(i); 
        int _id=c.getInt(c.getColumnIndex(TumblrDB._ID)); 
        Log.d("DeleteList", "The id has been added "+_id); 
        idList.add(_id); 
        new Thread() 
        { 
         public void run() 
         { 
          for(int i:idList) 
          { 
           db.delete(i); 
           Log.d("DeleteList", "The id has been deleted "+i); 
           handler.sendEmptyMessage(WHAT); 
          } 
         } 
        }.start(); 
       } 
      } 
     } 

    }); 

} 

} 

编辑尝试了不同的方法通过扩展SimpleCursorAdapter来解决这个问题:

if(row==null) 
    { 
     row=inflater.inflate(layout, null, false); 
     holder=new ViewHolder(row,position); 
     row.setTag(holder); 
     holder.check_del.setTag(position); 
    } 
    else 
    { 
     holder=(ViewHolder)row.getTag(); 
     holder.check_del.setOnClickListener(null); 
     holder.check_del.setTag(position); 
     if(hitList.get(position)) 
      holder.check_del.setChecked(true); 
     else 
      holder.check_del.setChecked(false); 
    } 

然后我有工具ented的OnClickListener为CheckBox:

 OnClickListener cbl=new OnClickListener(){ 

     @Override 
     public void onClick(View view) { 
      // TODO Auto-generated method stub 
      int position=(Integer)view.getTag(); 
      Log.d("CustomCursorAdapter", "The checkbox at postion "+position+" has been clicked"); 
      if(((CheckBox)view).isChecked()) 
      { 
       hitList.set(position, true); 
      } 
      else 
      { 
       hitList.set(position, false); 
      } 
     } 
    }; 

现在,当我试图访问我使用的ArrayList,它抛出一个ArrayOutOfBoundsException:

btn_del.setOnClickListener(new OnClickListener(){ 
     @Override 
     public void onClick(View view) { 
      // TODO Auto-generated method stub 
      new Thread() 
      { 
       public void run() 
       { 
        int count=lv.getCount(); 
        for(int i=0;i<count;i++) 
        { 
         if(adapter.hitList.get(i)) 
         { 
          db.delete(c.getInt(c.getColumnIndex(TumblrDB._ID))); 
         } 
        } 
       } 
      }.start(); 
      adapter.notifyDataSetChanged(); 
     } 
    }); 
+0

我不知道'CheckableLinearLayout'是什么,但如果你想从列表中选择多个项目,那么你可以使用“CheckBox”来完成它。您可以为'ListView'编写一个自定义适配器,并在其''getView'方法中将'onCheckedChangedListener'附加到该项目的'CheckBox',并根据所选项目的选中项目的'ArrayList'中的项目添加/删除该项目项目。 – Mehedi

+0

当通过覆盖newView和bindView方法做到这一点时,如果复选框已被选中,其他复选框会自动检查,如果我使用checkBox = null和/或checkBox.setChecked(false)来减轻这个影响,我发现我以前的checkBox当视图被回收时,选中的选项会被取消选中。您可以向我展示一些代码/说明如何在扩展SimpleCursorAdapter时避免这些副作用 – vamsiampolu

+0

我是否需要向此添加ListView.OnClickListener以使这些项目可点击。 – vamsiampolu

回答

1

使用一个ArrayList来存储所有的复选框的状态在列表中。

public static ArrayList<Boolean> hitList; 

我已经初始化并设置所有数值为false:

hitList=new ArrayList<Boolean>(); 
    for(int i=0;i<this.getCount();i++) 
    { 
     hitList.add(i, false); 
    } 

时,初始化复选框视图,它看起来的位置,并检查它只有在数组中ArrayList中的价值该位置由CheckBox使用setTag方法保存,并在Listener中检索以确定已检查的复选框的位置。调用重新查询从该行

@SuppressWarnings("deprecation") 
     @Override 
     public void onClick(View view) { 
      // TODO Auto-generated method stub 
      ArrayList<Boolean> killList=CustomCursorAdapter.hitList; 
      int totalDeleted=0; 
      for(int i=0;i<killList.size();i++) 
      { 
       //Log.d(TAG,i+":"+killList.get(i)); 
       c.moveToPosition(i); 
       String title=c.getString(c.getColumnIndex(ItemDB.TITLE)); 
       int _id=c.getInt(c.getColumnIndex(ItemDB._ID)); 
       //Log.d(TAG, "Item has title "+title+" and id "+_id); 
       int rowsAffected=0; 
       if(killList.get(i)) 
       { 
        rowsAffected=db.delete(_id); 
        //Log.d(TAG, "Deleted row with id "+_id); 
        killList.set(i, false); 

       } 
       totalDeleted+=rowsAffected; 

      } 
      //Log.d(TAG, "The total number of rows deleted "+totalDeleted); 
      //if(c.requery()) 
      //{ 
       //Log.d(TAG, "Requerying data,this calls notifyDataSetChanged"); 
      //} 

     }}); 

一次,你已经删除的数据,之前的光标(被弃用:

@Override 
public View getView(int position,View convertView,ViewGroup parent) 
{ 
    View row=convertView; 
    ViewHolder holder; 

    if(row==null) 
    { 
     row=inflater.inflate(layout, null, false); 
     holder=new ViewHolder(row); 
     row.setTag(holder); 
     holder.check_del.setTag(position); 
    } 
    else 
    { 
     holder=(ViewHolder)row.getTag(); 
     holder.check_del.setOnClickListener(null); 
     holder.check_del.setTag(position); 
     if(hitList.get(position)) 
      holder.check_del.setChecked(true); 
     else 
      holder.check_del.setChecked(false); 
    } 
    c.moveToPosition(position); 
    holder.txt_a.setText(c.getString(c.getColumnIndex(ItemDB.TITLE))); 
    holder.txt_b.setText(c.getString(c.getColumnIndex(ItemDB.DESCRIPTION))); 

    OnClickListener cbl=new OnClickListener(){ 

     @Override 
     public void onClick(View view) { 
      // TODO Auto-generated method stub 
      int position=(Integer)view.getTag(); 
      Log.d("CustomCursorAdapter", "The checkbox at postion "+position+" has been clicked"); 
      if(((CheckBox)view).isChecked()) 
      { 
       hitList.set(position, true); 
      } 
      else 
      { 
       hitList.set(position, false); 
      } 
     } 
    }; 

    holder.check_del.setOnClickListener(cbl); 
    return row; 
} 

static class ViewHolder 
{ 
    TextView txt_a; 
    TextView txt_b; 
    CheckBox check_del; 
    ViewHolder(View row) 
    { 
     txt_a=(TextView)row.findViewById(R.id.txt_a); 
     txt_b=(TextView)row.findViewById(R.id.txt_b); 
     check_del=(CheckBox)row.findViewById(R.id.check_del); 
    } 
} 

目前,我在它具有以下onClickListener ListView的头...需要找到更好的选择),ArrayList中的值必须重置。