Android:带有CheckBox的ListView,从SQLite数据库填充不太正常

前端之家收集整理的这篇文章主要介绍了Android:带有CheckBox的ListView,从SQLite数据库填充不太正常前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
与此处的其他几篇文章一样,我正在尝试创建一个ListView,其中包含每行的CheckBox,并使用sqlite数据库存储选择的当前状态.

http://appfulcrum.com/?p=351的示例开始,这个示例并不完全正常,我创建了一个创建数据库的简单应用程序,用20个项目填充它,并显示列表.

它成功检索状态并存储选择的状态.

但是,如果我更改它,它无法正确显示CheckBox状态,滚动到列表的另一端,然后向后滚动.例如如果我选择第一个CheckBox,滚动到底部,然后回到顶部,不再设置CheckBox.这是在Android 2.1三星手机上运行.

如果我返回主屏幕,返回列表,CheckBox已正确设置,因此数据库确实已更新.

该示例扩展了SimpleCursorAdapter,并且getView()根据表中选择列的值,根据需要使用true或false调用setChecked().

以下是所有来源.

我当然很感激被告知,“呃,这是你的问题……”

CustomListViewDB.java

  1. // src/CustomListViewDB.java
  2. package com.appfulcrum.blog.examples.listviewcustomdb;
  3.  
  4. import android.app.ListActivity;
  5. import android.database.Cursor;
  6. import android.database.sqlException;
  7. import android.os.AsyncTask;
  8. import android.os.Bundle;
  9. import android.view.View;
  10. import android.view.View.OnClickListener;
  11. import android.widget.Button;
  12. import android.widget.ListView;
  13. import android.widget.Toast;
  14.  
  15. public class CustomListViewDB extends ListActivity {
  16.  
  17. private ListView mainListView = null;
  18. CustomsqlCursorAdapter adapter = null;
  19. private sqlHelper dbHelper = null;
  20. private Cursor currentCursor = null;
  21.  
  22. private ListView listView = null;
  23.  
  24. /** Called when the activity is first created. */
  25. @Override
  26. public void onCreate(Bundle savedInstanceState) {
  27. super.onCreate(savedInstanceState);
  28. setContentView(R.layout.simple);
  29.  
  30. if (this.dbHelper == null) {
  31. this.dbHelper = new sqlHelper(this);
  32.  
  33. }
  34.  
  35. listView = getListView();
  36. listView.setItemsCanFocus(false);
  37. listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
  38. //listView.setClickable(true);
  39.  
  40. Button btnClear = (Button) findViewById(R.id.btnClear);
  41. btnClear.setOnClickListener(new OnClickListener() {
  42.  
  43. public void onClick(View v) {
  44. Toast.makeText(getApplicationContext()," You clicked Clear button",Toast.LENGTH_SHORT).show();
  45. ClearDBSelections();
  46. }
  47. });
  48.  
  49. new SelectDataTask().execute();
  50.  
  51. this.mainListView = getListView();
  52.  
  53. mainListView.setCacheColorHint(0);
  54.  
  55. }
  56.  
  57. @Override
  58. protected void onRestart() {
  59. super.onRestart();
  60. new SelectDataTask().execute();
  61. }
  62.  
  63. @Override
  64. protected void onPause() {
  65.  
  66. super.onPause();
  67. this.dbHelper.close();
  68. }
  69.  
  70. protected void ClearDBSelections() {
  71.  
  72. this.adapter.ClearSelections();
  73.  
  74. }
  75.  
  76. private class SelectDataTask extends AsyncTask<Void,Void,String> {
  77.  
  78. protected String doInBackground(Void... params) {
  79.  
  80. try {
  81.  
  82. CustomListViewDB.this.dbHelper.createDatabase(dbHelper.dbsqlite);
  83. CustomListViewDB.this.dbHelper.openDataBase();
  84.  
  85. CustomListViewDB.this.currentCursor = CustomListViewDB.this.dbHelper
  86. .getCursor();
  87.  
  88. } catch (sqlException sqle) {
  89.  
  90. throw sqle;
  91.  
  92. }
  93. return null;
  94. }
  95.  
  96. // can use UI thread here
  97. protected void onPostExecute(final String result) {
  98.  
  99. startManagingCursor(CustomListViewDB.this.currentCursor);
  100. int[] listFields = new int[] { R.id.txtTitle };
  101. String[] dbColumns = new String[] { sqlHelper.COLUMN_TITLE };
  102.  
  103. CustomListViewDB.this.adapter = new CustomsqlCursorAdapter(
  104. CustomListViewDB.this,R.layout.single_item,CustomListViewDB.this.currentCursor,dbColumns,listFields,CustomListViewDB.this.dbHelper);
  105. setListAdapter(CustomListViewDB.this.adapter);
  106.  
  107. }
  108. }
  109.  
  110. }

CustomsqlCursorAdapter.java

  1. // src/CustomsqlCursorAdapter.java
  2.  
  3. package com.appfulcrum.blog.examples.listviewcustomdb;
  4.  
  5. import android.content.ContentValues;
  6. import android.content.Context;
  7. import android.database.Cursor;
  8. import android.database.sqlException;
  9. import android.util.Log;
  10. import android.view.LayoutInflater;
  11. import android.view.View;
  12. import android.view.ViewGroup;
  13. import android.widget.CheckBox;
  14. import android.widget.CompoundButton;
  15. import android.widget.CompoundButton.OnCheckedChangeListener;
  16. import android.widget.SimpleCursorAdapter;
  17. import android.widget.TextView;
  18.  
  19. public class CustomsqlCursorAdapter extends SimpleCursorAdapter {
  20. private Context mContext;
  21.  
  22. private sqlHelper mDbHelper;
  23. private Cursor mCurrentCursor;
  24.  
  25. public CustomsqlCursorAdapter(Context context,int layout,Cursor c,String[] from,int[] to,sqlHelper dbHelper) {
  26. super(context,layout,c,from,to);
  27. this.mCurrentCursor = c;
  28. this.mContext = context;
  29. this.mDbHelper = dbHelper;
  30.  
  31. }
  32.  
  33. public View getView(int pos,View inView,ViewGroup parent) {
  34. View v = inView;
  35. if (v == null) {
  36. LayoutInflater inflater = (LayoutInflater) mContext
  37. .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  38. v = inflater.inflate(R.layout.single_item,null);
  39. }
  40.  
  41. if (!this.mCurrentCursor.moveToPosition(pos)) {
  42. throw new sqlException("CustomsqlCursorAdapter.getView: Unable to move to position: "+pos);
  43. }
  44.  
  45. CheckBox cBox = (CheckBox) v.findViewById(R.id.bcheck);
  46.  
  47. // save the row's _id value in the checkBox's tag for retrieval later
  48. cBox.setTag(Integer.valueOf(this.mCurrentCursor.getInt(0)));
  49.  
  50. if (this.mCurrentCursor.getInt(sqlHelper.COLUMN_SELECTED_idx) != 0) {
  51. cBox.setChecked(true);
  52. Log.w("sqlHelper","CheckBox true for pos "+pos+",id="+this.mCurrentCursor.getInt(0));
  53. } else {
  54. cBox.setChecked(false);
  55. Log.w("sqlHelper","CheckBox false for pos "+pos+",id="+this.mCurrentCursor.getInt(0));
  56. }
  57. //cBox.setOnClickListener(this);
  58. cBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
  59.  
  60. @Override
  61. public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
  62.  
  63. Log.w("sqlHelper","Selected a CheckBox and in onCheckedChanged: "+isChecked);
  64.  
  65. Integer _id = (Integer) buttonView.getTag();
  66. ContentValues values = new ContentValues();
  67. values.put(sqlHelper.COLUMN_SELECTED,isChecked ? Integer.valueOf(1) : Integer.valueOf(0));
  68. mDbHelper.dbsqlite.beginTransaction();
  69. try {
  70. if (mDbHelper.dbsqlite.update(sqlHelper.TABLE_NAME,values,"_id=?",new String[] { Integer.toString(_id) }) != 1) {
  71. throw new sqlException("onCheckedChanged Failed to update _id="+_id);
  72. }
  73. mDbHelper.dbsqlite.setTransactionSuccessful();
  74. } finally {
  75. mDbHelper.dbsqlite.endTransaction();
  76. }
  77.  
  78. Log.w("sqlHelper","-- _id="+_id+",isChecked="+isChecked);
  79. }
  80. });
  81.  
  82. TextView txtTitle = (TextView) v.findViewById(R.id.txtTitle);
  83. txtTitle.setText(this.mCurrentCursor.getString(this.mCurrentCursor
  84. .getColumnIndex(sqlHelper.COLUMN_TITLE)));
  85.  
  86. return (v);
  87. }
  88.  
  89. public void ClearSelections() {
  90. this.mDbHelper.clearSelections();
  91. this.mCurrentCursor.requery();
  92.  
  93. }
  94. }

ListViewWithDBActivity.java

  1. package com.appfulcrum.blog.examples.listviewcustomdb;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5.  
  6. public class ListViewWithDBActivity extends Activity {
  7. /** Called when the activity is first created. */
  8. @Override
  9. public void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.main);
  12. }
  13. }

提供sqlHelper

  1. // sqlHelper.java
  2.  
  3. package com.appfulcrum.blog.examples.listviewcustomdb;
  4.  
  5. import android.content.ContentValues;
  6. import android.content.Context;
  7. import android.database.Cursor;
  8. import android.database.sqlException;
  9. import android.database.sqlite.sqliteDatabase;
  10. import android.database.sqlite.sqliteOpenHelper;
  11. import android.database.sqlite.sqliteQueryBuilder;
  12. import android.database.sqlite.sqliteStatement;
  13. import android.util.Log;
  14.  
  15. public class sqlHelper extends sqliteOpenHelper {
  16. private static final String DATABASE_PATH = "/data/data/com.appfulcrum.blog.examples.listviewcustomdb/databases/";
  17.  
  18. public static final String DATABASE_NAME = "TODOList";
  19.  
  20. public static final String TABLE_NAME = "ToDoItems";
  21. public static final int ToDoItems_VERSION = 1;
  22.  
  23. public static final String COLUMN_ID = "_id"; // 0
  24. public static final String COLUMN_TITLE = "title"; // 1
  25. public static final String COLUMN_NAME_DESC = "description";// 2
  26. public static final String COLUMN_SELECTED = "selected"; // 3
  27. public static final int COLUMN_SELECTED_idx = 3;
  28.  
  29. public sqliteDatabase dbsqlite;
  30. private Context mContext;
  31.  
  32. public sqlHelper(Context context) {
  33. super(context,DATABASE_NAME,null,1);
  34. mContext = context;
  35. }
  36.  
  37. @Override
  38. public void onCreate(sqliteDatabase db) {
  39. createDB(db);
  40. }
  41.  
  42. @Override
  43. public void onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) {
  44. Log.w("sqlHelper","Upgrading database from version " + oldVersion
  45. + " to " + newVersion + ",which will destroy all old data");
  46.  
  47. db.execsql("DROP TABLE IF EXISTS ToDoItems;");
  48.  
  49. createDB(db);
  50. }
  51.  
  52. public void createDatabase(sqliteDatabase db) {
  53. createDB(db);
  54. }
  55.  
  56. private void createDB(sqliteDatabase db) {
  57. if (db == null) {
  58. db = mContext.openOrCreateDatabase(DATABASE_NAME,null);
  59. }
  60.  
  61. db.execsql("CREATE TABLE IF NOT EXISTS ToDoItems (_id INTEGER PRIMARY KEY,title TEXT,"
  62. +" description TEXT,selected INTEGER);");
  63. db.setVersion(ToDoItems_VERSION);
  64.  
  65. //
  66. // Generate a few rows for an example
  67. //
  68. // find out how many rows already exist,and make sure there's some minimum
  69. sqliteStatement s = db.compileStatement("select count(*) from ToDoItems;");
  70.  
  71. long count = s.simpleQueryForLong();
  72. for (int i = 0; i < 20-count; i++) {
  73. db.execsql("INSERT INTO ToDoItems VALUES(NULL,'Task #"+i+"','Description #"+i+"',0);");
  74. }
  75. }
  76.  
  77. public void openDataBase() throws sqlException {
  78. String myPath = DATABASE_PATH + DATABASE_NAME;
  79.  
  80. dbsqlite = sqliteDatabase.openDatabase(myPath,sqliteDatabase.OPEN_READWRITE);
  81. }
  82.  
  83. @Override
  84. public synchronized void close() {
  85. if (dbsqlite != null)
  86. dbsqlite.close();
  87.  
  88. super.close();
  89. }
  90.  
  91. public Cursor getCursor() {
  92. sqliteQueryBuilder queryBuilder = new sqliteQueryBuilder();
  93.  
  94. queryBuilder.setTables(TABLE_NAME);
  95.  
  96. String[] asColumnsToReturn = new String[] { COLUMN_ID,COLUMN_TITLE,COLUMN_NAME_DESC,COLUMN_SELECTED };
  97.  
  98. Cursor mCursor = queryBuilder.query(dbsqlite,asColumnsToReturn,COLUMN_ID+" ASC");
  99.  
  100. return mCursor;
  101. }
  102.  
  103. public void clearSelections() {
  104. ContentValues values = new ContentValues();
  105. values.put(COLUMN_SELECTED,0);
  106. this.dbsqlite.update(sqlHelper.TABLE_NAME,null);
  107. }
  108. }

Start.java

  1. //src/Start.java
  2. package com.appfulcrum.blog.examples.listviewcustomdb;
  3.  
  4. import android.app.Activity;
  5. import android.content.Intent;
  6. import android.os.Bundle;
  7. import android.view.View;
  8. import android.view.View.OnClickListener;
  9. import android.widget.Button;
  10. import android.widget.Toast;
  11.  
  12. public class Start extends Activity {
  13. /** Called when the activity is first created. */
  14. @Override
  15. public void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.main);
  18.  
  19. Button btnSimple = (Button) findViewById(R.id.btnSimple);
  20. btnSimple.setOnClickListener(new OnClickListener() {
  21.  
  22. public void onClick(View v) {
  23.  
  24. Toast.makeText(getApplicationContext()," You clicked ListView From DB button",Toast.LENGTH_SHORT).show();
  25.  
  26. Intent intent = new Intent(v.getContext(),CustomListViewDB.class);
  27. startActivityForResult(intent,0);
  28. }
  29. });
  30.  
  31. }
  32. }

布局/ main.xml中

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:id="@+id/buttonlayout" android:orientation="vertical"
  3. android:layout_width="fill_parent" android:layout_height="fill_parent"
  4. android:gravity="left|top" android:paddingTop="2dp"
  5. android:paddingBottom="2dp">
  6.  
  7. <TextView android:id="@+id/txtTest" android:layout_width="fill_parent"
  8. android:layout_height="wrap_content" android:textStyle="bold"
  9. android:text="@string/app_name" android:textSize="15sp"
  10. android:textColor="#FF0000" android:gravity="center_vertical"
  11. android:paddingLeft="5dp">
  12. </TextView>
  13.  
  14. <Button android:id="@+id/btnSimple"
  15. android:layout_width="fill_parent"
  16. android:layout_height="wrap_content"
  17. android:textSize="15sp"
  18. android:text="Listview from DB"
  19. android:textColor="#000000"
  20. >
  21. </Button>
  22.  
  23. </LinearLayout>

布局/ simple.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical" android:layout_width="fill_parent"
  4. android:layout_height="fill_parent">
  5.  
  6. <LinearLayout android:id="@+id/buttonlayout"
  7. android:orientation="horizontal" android:layout_width="fill_parent"
  8. android:layout_height="wrap_content" android:height="32dp"
  9. android:gravity="left|top" android:paddingTop="2dp"
  10. android:paddingBottom="2dp">
  11.  
  12. <LinearLayout android:id="@+id/buttonlayout2"
  13. android:orientation="horizontal" android:layout_height="wrap_content"
  14. android:gravity="left|center_vertical" android:layout_width="wrap_content"
  15. android:layout_gravity="left|center_vertical">
  16.  
  17. <TextView android:id="@+id/txtTest"
  18. android:layout_width="fill_parent"
  19. android:layout_height="fill_parent" android:textStyle="bold"
  20. android:text="@string/list_header" android:textSize="15sp"
  21. android:gravity="center_vertical" android:paddingLeft="5dp">
  22. </TextView>
  23.  
  24. <Button android:id="@+id/btnClear"
  25. android:layout_width="wrap_content"
  26. android:layout_height="wrap_content" android:text="Clear"
  27. android:textSize="15sp" android:layout_marginLeft="10px"
  28. android:layout_marginRight="10px"
  29. android:layout_marginBottom="2px"
  30. android:layout_marginTop="2px" android:height="15dp"
  31. android:width="70dp"></Button>
  32. </LinearLayout>
  33. </LinearLayout>
  34.  
  35. <TableLayout android:id="@+id/TableLayout01"
  36. android:layout_width="fill_parent" android:layout_height="fill_parent"
  37. android:stretchColumns="*">
  38. <TableRow>
  39. <ListView android:id="@android:id/list"
  40. android:layout_width="wrap_content"
  41. android:layout_height="wrap_content"></ListView>
  42. </TableRow>
  43.  
  44. </TableLayout>
  45.  
  46. </LinearLayout>

布局/ single_item.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent" android:layout_height="wrap_content"
  4. android:orientation="horizontal" android:gravity="center_vertical">
  5.  
  6. <CheckBox android:id="@+id/bcheck"
  7. android:layout_width="wrap_content"
  8. android:layout_height="fill_parent" />
  9.  
  10. <TextView android:id="@+id/txtTitle"
  11. android:layout_width="wrap_content" android:gravity="left|center_vertical"
  12. android:layout_height="?android:attr/listPreferredItemHeight"
  13. android:layout_alignParentLeft="true"
  14. android:textSize="20sp" android:text="Test"
  15. android:textStyle="bold" android:paddingLeft="5dp"
  16. android:paddingRight="2dp" android:focusable="false"
  17. android:focusableInTouchMode="false"></TextView>
  18. <LinearLayout android:layout_width="fill_parent"
  19. android:layout_height="wrap_content" android:orientation="horizontal"
  20. android:gravity="right|center_vertical">
  21. </LinearLayout>
  22.  
  23. </LinearLayout>

值/ strings.xml中

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <string name="hello">Hello World,ListViewWithDBActivity!</string>
  4. <string name="app_name">ListViewWithDB</string>
  5. <string name="list_header">List Headers</string>
  6. </resources>

AndroidManifest.xml中

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:versionCode="1" android:versionName="1.0"
  4. package="com.appfulcrum.blog.examples.listviewcustomdb">
  5.  
  6. <application android:icon="@drawable/icon"
  7. android:label="@string/app_name"
  8. android:theme="@android:style/Theme.NoTitleBar">
  9. >
  10. <activity android:name=".Start" android:label="@string/app_name">
  11. <intent-filter>
  12. <action android:name="android.intent.action.MAIN" />
  13. <category android:name="android.intent.category.LAUNCHER" />
  14. </intent-filter>
  15. </activity>
  16. <activity android:name=".CustomListViewDB"></activity>
  17. </application>
  18.  
  19. <uses-sdk android:minSdkVersion="7" /> <!-- android 1.6 -->
  20. </manifest>

如果你想构建,将一些任意的icon.png扔进drawable.

提前致谢.

解决方法

我发现异地问题最完整的解决方案.

Android ListView with CheckBox : Retain State

感谢帮助人员.

猜你在找的Android相关文章