Android save Checkbox State in ListView with Cursor Adapter
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.
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开发者_Python百科[] 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;
}
}
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)
The following worked for me. The example I have is a custom view that is provided an adaptor extended from SimpleCursorAdapter.
My custom view (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():
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.
I would recommend you use Android's built-in support for multiple-choice lists (CHOICE_MODE_MULTIPLE
).
The List11.java
SDK sample demonstrates this. You can also find a project from one of my tutorials that uses it here.
You can still use this technique with your own layout, so long as you include a CheckedTextView
with android:id="@android:id/text1"
as shown in the android.R.layout.simple_list_item_multiple_choice
resource, a copy of which ships with your SDK.
Also, see this question and this question and this question and this question.
Declare the CheckBox on getView Method and use this code
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
}
}});
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();
}
});
}
}
- CheckBox Open “res/layout/main.xml” file, add 3 “CheckBox” and a button, inside the LinearLayout.
File : 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>
精彩评论