Android 使用 Cursor Adapter 在 ListView 中保存复选框状态

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2406937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:44:52  来源:igfitidea点击:

Android save Checkbox State in ListView with Cursor Adapter

androidlistviewcheckboxstate

提问by Ricardo

I cant find a way to save the checkbox state when using a Cursor adapter. Everything else works fine but if i click on a checkbox it is repeated when it is recycled. Ive seen examples using array adapters but because of my lack of experience im finding it hard to translate it into using a cursor adapter. Could someone give me an example of how to go about it. Any help appreciated.

使用 Cursor 适配器时,我找不到保存复选框状态的方法。其他一切正常,但如果我点击一个复选框,它会在回收时重复。我见过使用数组适配器的示例,但由于我缺乏经验,我发现很难将其转换为使用游标适配器。有人可以给我一个如何去做的例子。任何帮助表示赞赏。

private class PostImageAdapter extends CursorAdapter {

    private static final int s = 0;
    private int layout;
    Bitmap bm=null;
    private String PostNumber;
    TourDbAdapter mDbHelper;


    public PostImageAdapter (Context context, int layout, Cursor c, String[] from, int[] to, String Postid) {

        super(context, c);
        this.layout = layout;
        PostNumber = Postid;

     mDbHelper = new TourDbAdapter(context);
     mDbHelper.open();

    }

    @Override
    public View newView(Context context, final Cursor c, ViewGroup parent) {

     ViewHolder holder;

     LayoutInflater inflater=getLayoutInflater();
     View row=inflater.inflate(R.layout.image_post_row, null);       

   holder = new ViewHolder();

   holder.Description = (TextView) row.findViewById(R.id.item_desc);
   holder.cb = (CheckBox) row.findViewById(R.id.item_checkbox);
   holder.DateTaken = (TextView) row.findViewById(R.id.item_date_taken);
   holder.Photo = (ImageView) row.findViewById(R.id.item_thumb);

   row.setTag(holder);

 int DateCol = c.getColumnIndex(TourDbAdapter.KEY_DATE);
 String Date = c.getString(DateCol);

 int DescCol = c.getColumnIndex(TourDbAdapter.KEY_CAPTION);
 String Description = c.getString(DescCol);    

 int FileNameCol = c.getColumnIndex(TourDbAdapter.KEY_FILENAME); 
 final String FileName = c.getString(FileNameCol);

 int PostRowCol = c.getColumnIndex(TourDbAdapter.KEY_Post_ID); 
 String RowID = c.getString(PostRowCol);

 String Path = "sdcard/Tourabout/Thumbs/" + FileName + ".jpg";    
 Bitmap bm = BitmapFactory.decodeFile(Path, null); 

 holder.Photo.setImageBitmap(bm);
 holder.DateTaken.setText(Date);
 holder.Description.setText(Description);

 holder.cb.setOnClickListener(new OnClickListener() {  
    @Override
 public void onClick(View v) {
    CheckBox cBox = (CheckBox) v;
    if (cBox.isChecked()) {

      mDbHelper.UpdatePostImage(FileName, PostNumber);

    } 
    else if (!cBox.isChecked()) {    
      mDbHelper.UpdatePostImage(FileName, "");

    }

  }
});
return row;

};

    @Override
    public void bindView(View row, Context context, final Cursor c) {  

     ViewHolder holder;
     holder = (ViewHolder) row.getTag();   

      int DateCol = c.getColumnIndex(TourDbAdapter.KEY_DATE);
         String Date = c.getString(DateCol);

         int DescCol = c.getColumnIndex(TourDbAdapter.KEY_CAPTION);
         String Description = c.getString(DescCol);    

         int FileNameCol = c.getColumnIndex(TourDbAdapter.KEY_FILENAME); 
      final String FileName = c.getString(FileNameCol);

      int PostRowCol = c.getColumnIndex(TourDbAdapter.KEY_Post_ID); 
         String RowID = c.getString(PostRowCol);

      String Path = "sdcard/Tourabout/Thumbs/" + FileName + ".jpg";    
         Bitmap bm = BitmapFactory.decodeFile(Path, null); 

        File x = null;

         holder.Photo.setImageBitmap(bm);
         holder.DateTaken.setText(Date);
         holder.Description.setText(Description);

         holder.cb.setOnClickListener(new OnClickListener() {  
        @Override
        public void onClick(View v) {
         CheckBox cBox = (CheckBox) v;
         if (cBox.isChecked()) {

               mDbHelper.UpdatePostImage(FileName, PostNumber);

         } 
         else if (!cBox.isChecked()) {    
               mDbHelper.UpdatePostImage(FileName, "");

         }

        }
       });

    }

}  

static class ViewHolder{
  TextView Description;
  ImageView Photo;
  CheckBox cb;
  TextView DateTaken;
}
}

采纳答案by CommonsWare

I would recommend you use Android's built-in support for multiple-choice lists (CHOICE_MODE_MULTIPLE).

我建议您使用 Android 对多项选择列表 ( CHOICE_MODE_MULTIPLE)的内置支持。

The List11.javaSDK sample demonstrates this. You can also find a project from one of my tutorials that uses it here.

List11.javaSDK示例演示了这一点。您也可以找到我的教程的一个使用它的一个项目在这里

You can still use this technique with your own layout, so long as you include a CheckedTextViewwith android:id="@android:id/text1"as shown in the android.R.layout.simple_list_item_multiple_choiceresource, a copy of which ships with your SDK.

您仍然可以在您自己的布局中使用此技术,只要您包含资源中所示的CheckedTextViewwith ,其副本随您的 SDK 一起提供。android:id="@android:id/text1"android.R.layout.simple_list_item_multiple_choice

Also, see this questionand this questionand this questionand this question.

另外,请参阅this questionthis question以及this questionthis question

回答by Nazar

I had the same issue myself: how to toggle multiple select CheckedTextView in a custom layout (i.e not using android.R.layout.simple_list_item_multiple_choice)

我自己也遇到了同样的问题:如何在自定义布局中切换多选 CheckedTextView(即不使用android.R.layout.simple_list_item_multiple_choice

The following worked for me. The example I have is a custom view that is provided an adaptor extended from SimpleCursorAdapter.

以下对我有用。我的示例是一个自定义视图,它提供了一个从SimpleCursorAdapter扩展的适配器

My custom view (row_contact.xml):

我的自定义视图(row_contact.xml):

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_height="wrap_content" android:layout_width="fill_parent">

  <CheckedTextView
    android:id="@android:id/text1"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:gravity="center_vertical"
    android:paddingLeft="6dip"
    android:paddingRight="6dip" 
    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
    />

  <TextView
    android:text="@+id/TextView01"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tvNumber"
    android:layout_gravity="bottom" 
    android:paddingLeft="6dip"
    android:paddingRight="6dip" 
    />

</FrameLayout>

The adaptor is created in ListActivity.OnCreate, which calls setupViews():

适配器在 ListActivity.OnCreate 中创建,它调用 setupViews():

  private void setupViews() {
    bOk       = (Button) findViewById(R.id.ButtonOK);
    bCancel   = (Button) findViewById(R.id.ButtonCancel);
    FListView = getListView(); 
    //
    bOk.setText("Select");
    //
    FListView.setItemsCanFocus(false);
    FListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    //
    bOk.setOnClickListener(this);
    bCancel.setOnClickListener(this);
    //
    ContentResolver content = getContentResolver();
    Cursor cursor = ApplicationHelper.MobilePhoneContacts(content);
    startManagingCursor(cursor);

    ListAdapter adapter = new CheckedCursorAdapter( SelectContacts.this, R.layout.row_contact, cursor,                
        new String[] {People.NAME, People.NUMBER},               
        new int[] {android.R.id.text1, R.id.tvNumber});          
    setListAdapter(adapter);
  }

The Custom adaptor:

自定义适配器:

  public class CheckedCursorAdapter extends SimpleCursorAdapter {

    Activity context;
    Cursor c;

    public CheckedCursorAdapter(Activity context, int rowContact, Cursor cursor, String[] strings, int[] is) {
      super(context, rowContact, cursor, strings, is);
      this.context = context;
      this.c = cursor;

    }

    public View getView(int position, View convertView, ViewGroup parent) {
      View row = convertView;
      ContactRowWrapper wrapper;

      if (row == null) {
        LayoutInflater inflater=context.getLayoutInflater();
        row = inflater.inflate(R.layout.row_contact, null);
        //
        wrapper = new ContactRowWrapper(row);
        row.setTag(wrapper);
      } else {
        wrapper = (ContactRowWrapper)row.getTag();
      }
      c.moveToPosition(position);
      wrapper.getTextView().setText( c.getString(c.getColumnIndex(Contacts.People.NUMBER)) );
      wrapper.getcheckBox().setText( c.getString(c.getColumnIndex(Contacts.People.NAME)) );
      wrapper.getcheckBox().setChecked(getListView().isItemChecked(position));
      //
      return row;
    }

  }

The crucial bit of code for for me was to get check boxes working was:

对我来说,让复选框工作的关键代码是:

wrapper.getcheckBox().setChecked(getListView().isItemChecked(position));

Hope this helps you or anyone else who stumbles onto this question.

希望这可以帮助您或任何偶然发现这个问题的人。

Also, pardon my Java noobness... I've only started Java a few weeks ago.

另外,请原谅我的 Java 菜鸟...几周前我才开始使用 Java。

回答by ranjit patel

Declare the CheckBox on getView Method and use this code

在 getView 方法上声明 CheckBox 并使用此代码

CheckBox  checkBtn =(CheckBox) convertView.findViewById(R.id.phCheckBox);
                 checkBtn.setChecked(Boolean.parseBoolean((vList.get(position).getCheckBtnStatus())));

             checkBtn.setOnClickListener(new OnClickListener() 
              {

                  public void onClick(View arg0) 
                  {

                      if(checkBtn.isChecked()==true)
                          {
                          vList.get(position).setCheckBtnStatus("true");

                        System.out.println("vList.get(position)---"+vList.get(position).getCheckBtnStatus()+" -"+position);
                          }
                      else
                      {
                          vList.get(position).setCheckBtnStatus("false");
                        System.out.println("else vList.get(position)---"+vList.get(position).getCheckBtnStatus()+"-"+position);
                      }

                  }
              });

After that on the main Activity u have to check which position of checkbox is true

之后在主活动上你必须检查复选框的哪个位置是真的

save.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {


            for (int i = 0; i < newList.size(); i++) {
                UserData v1 = newList.get(i);
                status = Boolean.parseBoolean(v1.getCheckBtnStatus());

                if (status == true) {

                            //write ur code here 
                }

            }});

回答by Anup Agrawal

3. Code Code
Attach listeners inside your activity “onCreate()” method, to monitor following events :

If checkbox id : “chkIos” is checked, display a floating box with message “Bro, try Android”.
If button is is clicked, display a floating box and display the checkbox states.
File : MyAndroidAppActivity.java

package com.mkyong.android;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Toast;

public class MyAndroidAppActivity extends Activity {

  private CheckBox chkIos, chkAndroid, chkWindows;
  private Button btnDisplay;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    addListenerOnChkIos();
    addListenerOnButton();
  }

  public void addListenerOnChkIos() {

    chkIos = (CheckBox) findViewById(R.id.chkIos);

    chkIos.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View v) {
                //is chkIos checked?
        if (((CheckBox) v).isChecked()) {
            Toast.makeText(MyAndroidAppActivity.this,
               "Bro, try Android :)", Toast.LENGTH_LONG).show();
        }

      }
    });

  }

  public void addListenerOnButton() {

    chkIos = (CheckBox) findViewById(R.id.chkIos);
    chkAndroid = (CheckBox) findViewById(R.id.chkAndroid);
    chkWindows = (CheckBox) findViewById(R.id.chkWindows);
    btnDisplay = (Button) findViewById(R.id.btnDisplay);

    btnDisplay.setOnClickListener(new OnClickListener() {

          //Run when button is clicked
      @Override
      public void onClick(View v) {

        StringBuffer result = new StringBuffer();
        result.append("IPhone check : ").append(chkIos.isChecked());
        result.append("\nAndroid check : ").append(chkAndroid.isChecked());
        result.append("\nWindows Mobile check :").append(chkWindows.isChecked());

        Toast.makeText(MyAndroidAppActivity.this, result.toString(),
                Toast.LENGTH_LONG).show();

      }
    });

  }
}

回答by Rupesh Kumar

  1. CheckBox Open “res/layout/main.xml” file, add 3 “CheckBox” and a button, inside the LinearLayout.
  1. CheckBox 打开“res/layout/main.xml”文件,在LinearLayout里面添加3个“CheckBox”和一个按钮。

File : res/layout/main.xml

文件:res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <CheckBox
        android:id="@+id/chkIos"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/chk_ios" />

    <CheckBox
        android:id="@+id/chkAndroid"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/chk_android"
        android:checked="true" />

    <CheckBox
        android:id="@+id/chkWindows"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/chk_windows" />

    <Button
        android:id="@+id/btnDisplay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/btn_display" />

</LinearLayout>