【问题标题】:How to make a checkbox from information found in DataBase?如何根据数据库中的信息制作复选框?
【发布时间】:2017-11-28 14:05:22
【问题描述】:

我在数据库中有一个表,我想创建一个表。 现在我会做很多CheckBox并根据表格中的信息只显示其中一些是没有意义的。我听说了 但是怎么办我在网上找到了的例子,当我试图插入大量信息时,只有一半的信息进来,所以我被告知要做。 你有一个如何做到这一点的例子吗?

它的数据库处理程序:

package budgetreport.com.budgetreport;

public class DatabaseHandler extends SQLiteOpenHelper {

    // All Static variables
    // Database Version
    private static final int DATABASE_VERSION = 4;

    // Database Name
    private static final String DATABASE_NAME = "Records_Item Purcashes";

    // Contacts table name
    private static final String TABLE_RECORDS = "Records";

    // Contacts Table Columns names
    private static final String KEY_ID = "ID";
    private static final String KEY_PRICE = "Price";
    private static final String KEY_ITEM = "Item";
    private static final String KEY_DETAILS = "Details";
    private static final String KEY_DATE = "Date";

    public DatabaseHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    // Creating Tables
    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_RECORDS + "("
                + KEY_ID + " INTEGER PRIMARY KEY,"
                + KEY_PRICE + " INTEGER," + KEY_ITEM + " TEXT,"
                + KEY_DETAILS + " TEXT, " + KEY_DATE + " TEXT" + ")";
        db.execSQL(CREATE_CONTACTS_TABLE);
    }

    // Upgrading database
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_RECORDS);

        // Create tables again
        onCreate(db);
    }
    // Adding new contact
    public void addRecord(Record record) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();

        values.put(KEY_ID, record.getId()); // Contact Name
        values.put(KEY_PRICE, record.getPrice()); // Contact Name
        values.put(KEY_ITEM, record.getItem()); // Contact Name
        values.put(KEY_DETAILS, record.getDetails()); // Contact Name
        values.put(KEY_DATE, record.getDetails()); // Contact Phone Number

        // Inserting Row
        db.insert(TABLE_RECORDS, null, values);
        db.close(); // Closing database connection
    }
    // Getting single contact
    public Record getRecord(int id) {
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(TABLE_RECORDS, new String[] { KEY_ID, KEY_PRICE,
                        KEY_ITEM, KEY_DETAILS, KEY_DATE }, KEY_ID + "=?",
                new String[] { String.valueOf(id) }, null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        Record record = new Record(Integer.parseInt(cursor.getString(0)),
                Integer.parseInt(cursor.getString(1)), cursor.getString(2), cursor.getString(3), cursor.getString(4));
        // return contact
        return record;
    }
    // Getting All Contacts
    public List<Record> getAllContacts() {
        List<Record> contactList = new ArrayList<Record>();
        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE_RECORDS;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                Record record = new Record();
                record.setId(Integer.parseInt(cursor.getString(0)));
                record.setPrice(Integer.parseInt(cursor.getString(1)));
                record.setItem(cursor.getString(2));
                record.setDetails(cursor.getString(3));
                record.setDate(cursor.getString(4));

                // Adding contact to list
                contactList.add(record);
            } while (cursor.moveToNext());
        }

        // return contact list
        return contactList;
    }
    // Getting contacts Count
    public int getRecordsCount() {
        String countQuery = "SELECT  * FROM " + TABLE_RECORDS;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);
       // cursor.close();

        // return count
        return cursor.getCount();
    }
    // Updating single contact
    public int updateContact(Record record) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_ID, record.getId());
        values.put(KEY_PRICE, record.getPrice());
        values.put(KEY_DETAILS, record.getDetails());
        values.put(KEY_DATE, record.getDate());

        // updating row
        return db.update(TABLE_RECORDS, values, KEY_ID + " = ?",
                new String[] { String.valueOf(record.getPrice()) });
    }
    // Deleting single contact
    public void deleteContact(Record record) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_RECORDS, KEY_ID + " = ?",new String[] 
       {String.valueOf(record.getPrice()) });
        db.close();
    }
}

【问题讨论】:

标签: listview listview checkbox listview adapter android listview arraylist android-sqlite checkboxlist


【解决方案1】:

删除检查项目 我想删除我标记的行。

这是相对简单的进展。

它涉及 - a) 向数据库助手添加一个方法以根据 id 删除。 - b) (i) 修改onClick 监听器以调用删除方法(简单循环),然后 (ii) 更新列表视图(循环后)。

但是,原来的自定义适配器有一些缺陷,原来的光标是通过 mCsr 保留的,并且没有考虑更改(交换)光标时更改的复选框的数量。

因此,适配器已删除了对 mCsr 的引用,并由传递的 Cursor 或通过调用 getCursor 方法替换。此外,swapCursor() 方法已被覆盖,以调整 mCheckBoxes 的元素数量并重新初始化 elemnets(设置为 false)。

a) 新的 deleteRecord 方法:-

public boolean deleteRecord(long id) {
    SQLiteDatabase db = this.getWritableDatabase();
     return (db.delete(TABLE_RECORDS,KEY_ID + "=?",new String[]{Long.toString(id)})> 0);
}

b)(i) onCLickListener 修正(注意包括将所有删除分组到一个事务中):-

    // <<<<< DO IT BUTTON HANDLER i.e. get list of ID's for checked items
    mDoItButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // get the ID's for the checked Items
            mCheckedIdList = mMCA.getCheckedRecordIdList();
            Toast.makeText(mContext,"You have " + mCheckedIdList.length + " Items checked.",Toast.LENGTH_SHORT).show();
            //<<<< to delete
            SQLiteDatabase db = mDBHandler.getWritableDatabase();
            db.beginTransaction();
            for (long id: mCheckedIdList) {
                mDBHandler.deleteRecord(id);
            }
            db.setTransactionSuccessful();
            db.endTransaction();
            refreshListView();
        }
    });

b(ii) 更新 Listview(Activity 中的新方法):-

private void refreshListView() {
    mCsr = mDBHandler.getAllRecords();
    mMCA.swapCursor(mCsr);
}

注意事项

  • 这是作为方法添加到活动中的。
  • mMCA.notifyDatasetChanged();是另一种选择(我个人更喜欢 `swapCursor1,因为它更具描述性)。

修改后的自定义光标适配器应该是:-

public class MyCustomCursorAdapter extends CursorAdapter {

    private Context mContext;
    private String[] mColumns;
    private int[] mViews;
    private int mLayout;
    private boolean[] mCheckBoxStates;
    private int mCheckBoxView;

    // Constructor for the Custom Cursor Adapter
    MyCustomCursorAdapter(Context context, int layout, Cursor csr, String[] from_columns, int[] to_views, int checkbox_view) {
        super(context,csr, false);
        mContext = context;
        mLayout = layout;
        mColumns = from_columns;
        mViews = to_views;
        mCheckBoxView = checkbox_view;
    }

    @Override
    // Inflate the layout we are going to use (as passed via 2nd parameter)
    public View newView(Context context, Cursor csr, ViewGroup parent) {
        // Initialise an int array for the checkboxes (all will be 0)
        mCheckBoxStates = new boolean[csr.getCount()];
        return LayoutInflater.from(context).inflate(mLayout,parent,false);
    }

    @Override
    // Tie the from_columns to the display views
    public void bindView(View view, Context context, Cursor csr) {

        final Cursor fcsr = csr;

        // Place the data from the cursor into the respective View (TextView)
        for (int i = 0; i < mColumns.length; i++) {
            ((TextView) view.findViewById(mViews[i])).setText(csr.getString(csr.getColumnIndex(mColumns[i])));
        }
        // Set the checkbox (note should be false, unless otherwise changed)
        CheckBox currentCheckBox = (CheckBox) view.findViewById(mCheckBoxView);
        currentCheckBox.setChecked(mCheckBoxStates[csr.getPosition()]);
        currentCheckBox.setTag(new Long(csr.getLong(csr.getColumnIndex(DatabaseHandler.KEY_ID))));

        //
        currentCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            final int position = fcsr.getPosition();
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // Store the checkbox status
                mCheckBoxStates[position] = ((CheckBox) buttonView).isChecked();
                int restore_cursor_position = fcsr.getPosition();
                //Move the Cursor to the respective row
                //NOTE! 1st position in Lisview is 1 but equates to cursor row 0 etc hence -1
                fcsr.moveToPosition(position);
                Toast.makeText(mContext,
                        "You Changed the CheckBox for row " +
                                Integer.toString(position + 1) +
                                " Item is " +
                                fcsr.getString(fcsr.getColumnIndex(DatabaseHandler.KEY_ITEM))
                        ,
                        Toast.LENGTH_SHORT
                ).show();
                //restore the Cursor's position
                fcsr.moveToPosition(restore_cursor_position);
            }
        });
    }

    // get the list of items (the ID's as long) that have been checked.
    public long[] getCheckedRecordIdList() {

        Cursor csr = this.getCursor();

        // using ArrayList as we can add as we don't yet know how many
        ArrayList<Long> rva = new ArrayList<>();
        // Just in case save the current position of the Cursor
        int restore_cursor_position = csr.getPosition();
        // Loop through the checkbox states
        for (int i=0; i < mCheckBoxStates.length; i++) {
            // If the checkbox reflected as being checked then handle, else ignore it
            if (mCheckBoxStates[i]) {
                // Move to the respective cursor row
                csr.moveToPosition(i);
                // get the respective ID and store in the arraylist
                rva.add(csr.getLong(csr.getColumnIndex(DatabaseHandler.KEY_ID)));
            }
        }
        // Done with the Cursor so re-position it
        csr.moveToPosition(restore_cursor_position);

        // Create the long array to be returned
        long[] rv = new long[rva.size()];
        // Populate the long array with the id's from the arraylist
        for (int i=0; i < rva.size(); i++) {
            rv[i] = rva.get(i);
        }
        // return the long[]
        return rv;
    }


    @Override
    public Cursor swapCursor(Cursor csr) {
        mCheckBoxStates = new boolean[csr.getCount()];
        for (int i=0; i < mCheckBoxStates.length; i++) {
            mCheckBoxStates[i] = false;
        }
        return super.swapCursor(csr);
    }
}

【讨论】:

  • 能否请您告知 getCheckedRecordIdList() 在哪里被调用?
  • 我的 checkBoxStates 也没有被保存?有没有办法做到这一点?
  • Do It 按钮的 onClickListener 中,请参阅 b(i) in the asnwer ie by mCheckedIdList = mMCA.getCheckedRecordIdList();
  • 您可以在表格中添加一个新列以及处理复选框状态的方法。
【解决方案2】:

这是一个基于您的代码的示例。

1) Activity 的布局(即 ID 为 lv001 的 ListView)作为文件 activity_main.xml :-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="mjt.budgetreport.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:layout_margin="10dp"
        />

    <ListView
        android:id="@+id/lv001"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>

</LinearLayout>

2) 每行的布局(ListView 术语中的Item)作为文件listviewitem_record.xml

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

    <TextView
        android:id="@+id/record_price"
        android:layout_width="0dp"
        android:layout_weight="8"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>
    <TextView
        android:id="@+id/record_item"
        android:layout_width="0dp"
        android:layout_weight="10"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>
    <TextView
        android:id="@+id/record_details"
        android:layout_width="0dp"
        android:layout_weight="20"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>
    <TextView
        android:id="@+id/record_date"
        android:layout_width="0dp"
        android:layout_weight="10"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>
    <CheckBox
        android:id="@+id/record_checkbox"
        android:layout_width="0dp"
        android:layout_weight="2"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>
</LinearLayout>
  • 注意!包含 CheckBox 以及所有列的 TextView。

3) 为了简化问题,我将其用作 DatabaseHandler.java :-

public class DatabaseHandler extends SQLiteOpenHelper {

    // All Static variables
    // Database Version
    private static final int DATABASE_VERSION = 4;

    // Database Name
    public static final String DATABASE_NAME = "Records_Item Purcashes";

    // Contacts table name
    public static final String TABLE_RECORDS = "Records";

    // Contacts Table Columns names
    public static final String KEY_ID = "_id";
    public static final String KEY_PRICE = "Price";
    public static final String KEY_ITEM = "Item";
    public static final String KEY_DETAILS = "Details";
    public static final String KEY_DATE = "Date";

    public DatabaseHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    // Creating Tables
    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_CONTACTS_TABLE = "CREATE TABLE " +
                TABLE_RECORDS +
                "(" +
                KEY_ID + " INTEGER PRIMARY KEY," +
                KEY_PRICE + " INTEGER," +
                KEY_ITEM + " TEXT," +
                KEY_DETAILS + " TEXT, " +
                KEY_DATE + " TEXT" +
                ")";
        db.execSQL(CREATE_CONTACTS_TABLE);
    }

    // Upgrading database
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_RECORDS);

        // Create tables again
        onCreate(db);
    }

    public void insertRecord(int price, String item, String details, String date) {
        ContentValues cv = new ContentValues();
        cv.put(KEY_PRICE,price);
        cv.put(KEY_ITEM,item);
        cv.put(KEY_DETAILS,details);
        cv.put(KEY_DATE,date);
        SQLiteDatabase db = this.getWritableDatabase();
        db.insert(TABLE_RECORDS,null,cv);
    }

    public Cursor getAllRecords() {
        SQLiteDatabase db = this.getWritableDatabase();
        return db.query(TABLE_RECORDS,null,null,null,null,null,null);
    }
    /*
    // Adding new contact
    public void addRecord(AlphabeticIndex.Record record) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();

        values.put(KEY_ID, record.getId()); // Contact Name
        values.put(KEY_PRICE, record.getPrice()); // Contact Name
        values.put(KEY_ITEM, record.getItem()); // Contact Name
        values.put(KEY_DETAILS, record.getDetails()); // Contact Name
        values.put(KEY_DATE, record.getDetails()); // Contact Phone Number

        // Inserting Row
        db.insert(TABLE_RECORDS, null, values);
        db.close(); // Closing database connection
    }
    */
    /*
    // Getting single contact
    public AlphabeticIndex.Record getRecord(int id) {
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(TABLE_RECORDS, new String[] { KEY_ID, KEY_PRICE,
                        KEY_ITEM, KEY_DETAILS, KEY_DATE }, KEY_ID + "=?",
                new String[] { String.valueOf(id) }, null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        AlphabeticIndex.Record record = new AlphabeticIndex.Record(Integer.parseInt(cursor.getString(0)),
                Integer.parseInt(cursor.getString(1)), cursor.getString(2), cursor.getString(3), cursor.getString(4));
        // return contact
        return record;
    }
    */

    /*
    // Getting All Contacts
    public List<AlphabeticIndex.Record> getAllContacts() {
        List<AlphabeticIndex.Record> contactList = new ArrayList<AlphabeticIndex.Record>();
        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE_RECORDS;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                AlphabeticIndex.Record record = new AlphabeticIndex.Record();
                record.setId(Integer.parseInt(cursor.getString(0)));
                record.setPrice(Integer.parseInt(cursor.getString(1)));
                record.setItem(cursor.getString(2));
                record.setDetails(cursor.getString(3));
                record.setDate(cursor.getString(4));

                // Adding contact to list
                contactList.add(record);
            } while (cursor.moveToNext());
        }

        // return contact list
        return contactList;
    }
    */

    /*
    // Getting contacts Count
    public int getRecordsCount() {
        String countQuery = "SELECT  * FROM " + TABLE_RECORDS;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);
        // cursor.close();

        // return count
        return cursor.getCount();
    }
    */

    /*
    // Updating single contact
    public int updateContact(AlphabeticIndex.Record record) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_ID, record.getId());
        values.put(KEY_PRICE, record.getPrice());
        values.put(KEY_DETAILS, record.getDetails());
        values.put(KEY_DATE, record.getDate());

        // updating row
        return db.update(TABLE_RECORDS, values, KEY_ID + " = ?",
                new String[] { String.valueOf(record.getPrice()) });
    }
    */
    /*
    // Deleting single contact
    public void deleteContact(AlphabeticIndex.Record record) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_RECORDS, KEY_ID + " = ?",new String[]
                {String.valueOf(record.getPrice()) });
        db.close();
    }
    */
}

DatabaseHandler.java 变更说明

  • rowid 别名已从 ID 更改为 _id,这是因为 CursorAdapter 需要一个名为 _id 的列和该列应该是 rowid 的别名(此处不涉及技术细节)。

  • 为了方便起见,我没有使用 Record 类,而是注释掉了使用该类的代码。

  • 我已将 TABLE 和 COLUMN 名称定义更改为 public,因此可以在其他地方访问它们。

  • 我添加了两个新方法insertRecordgetAllRecords:-

    • insertRecord 只是为了添加一些数据用于测试/示例
    • getAllRecordsCursor 形式检索所有行,而不是数组。
    • 注意! 数据库未关闭,这将导致异常,因为光标需要访问数据库(打开和关闭数据库无论如何都可能是有害的)。

4) Activity 本身(第一次运行添加一些数据后仅显示 ListView)作为文件 MainActivity.java :-

public class MainActivity extends AppCompatActivity {

    DatabaseHandler mDBHandler;
    ListView mListView;
    SimpleCursorAdapter mSCA;
    Cursor mCsr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListView = (ListView) this.findViewById(R.id.lv001); // Get the ListView from it's id
        mDBHandler = new DatabaseHandler(this); // Get an instance of the Database Handler

        // Add some data but only if there is no data
        if (DatabaseUtils.queryNumEntries(mDBHandler.getWritableDatabase(),DatabaseHandler.TABLE_RECORDS) < 1) {

            mDBHandler.insertRecord(100,"Rock","A large stone.","31/12/2017");
            mDBHandler.insertRecord(50,"Boulder","A Rock.","31/12/2018");
            mDBHandler.insertRecord(322,"Soil","Loose earth.","31/7/2015");
            mDBHandler.insertRecord(237,"Stone","A small rock.","31/8/2014");
            mDBHandler.insertRecord(32,"Pebble","A small smooth stone.","11/12/2017");
        }

        // get all rows into a Cursor
        mCsr = mDBHandler.getAllRecords();

        // Prepare a list of the columns to get the data from, for the ListViewt
        String[] columns_to_get_data_from = new String[]{
                DatabaseHandler.KEY_PRICE,
                DatabaseHandler.KEY_ITEM,
                DatabaseHandler.KEY_DETAILS,
                DatabaseHandler.KEY_DATE
        };

        // Prepare a list of the Views into which to place the data
        int[] itemviews_to_place_data_in = new int[]{
                R.id.record_price,
                R.id.record_item,
                R.id.record_details,
                R.id.record_date
        };

        // get and instance of SimpleCursorAdapter
        mSCA = new SimpleCursorAdapter(this,
                R.layout.listviewitem_record,
                mCsr,
                columns_to_get_data_from,
                itemviews_to_place_data_in,
                0);
        // get and instance of SimpleCursorAdapter the listviewitem_record layout
        mListView.setAdapter(mSCA);
    }
}

结果:-

注意事项

这不涉及处理复选框,这可能需要一个 CustomAdapter。有很多教程,例如how do i create a custom cursor adapter for a listview for use with images and text?.

修改为包含 CheckBox 处理

1) Activity 的布局 activity_main.xml - 添加了一个用于获取已检查项目的按钮:-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="mjt.budgetreport.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:layout_margin="10dp"
        />

    <Button
        android:id="@+id/doitbutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="DO ALL CHECKED ROWS"
        />

    <ListView
        android:id="@+id/lv001"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>

</LinearLayout>

2) 自定义光标适配器 MyCustomCursorAdapter.java

  • 类似于 SimpleCursorAdapter 的签名,但为 CheckBoxid 增加了一个额外参数。
  • 包括方法 getCheckedRecordIdList,它将返回已检查的 Id 列表。
  • 在选中或未选中复选框时发出敬酒,该举例说明该项目,如ListView的Item#(不是表中的项目),单击,然后单击项目单击(如图中所示)表中的值)。

:-

public class MyCustomCursorAdapter extends CursorAdapter {

    private Context mContext;
    private Cursor mCsr;
    private String[] mColumns;
    private int[] mViews;
    private int mLayout;
    private boolean[] mCheckBoxStates;
    private int mCheckBoxView;

    // Constructor for the Custom Cursor Adapter
    MyCustomCursorAdapter(Context context, int layout, Cursor csr, String[] from_columns, int[] to_views, int checkbox_view) {
        super(context,csr, false);
        mContext = context;
        mLayout = layout;
        mCsr = csr;
        mColumns = from_columns;
        mViews = to_views;
        mCheckBoxView = checkbox_view;
    }

    @Override
    // Inflate the layout we are going to use (as passed via 2nd parameter)
    public View newView(Context context, Cursor csr, ViewGroup parent) {
        // Initialise an int array for the checkboxes (all will be 0)
        mCheckBoxStates = new boolean[csr.getCount()];
        return LayoutInflater.from(context).inflate(mLayout,parent,false);
    }

    @Override
    // Tie the from_columns to the display views
    public void bindView(View view, Context context, Cursor csr) {

        // Place the data from the cursor into the respective View (TextView)
        for (int i = 0; i < mColumns.length; i++) {
            ((TextView) view.findViewById(mViews[i])).setText(csr.getString(csr.getColumnIndex(mColumns[i])));
        }
        // Set the checkbox (note should be false, unless otherwise changed)
        CheckBox currentCheckBox = (CheckBox) view.findViewById(mCheckBoxView);
        currentCheckBox.setChecked(mCheckBoxStates[mCsr.getPosition()]);
        currentCheckBox.setTag(new Long(mCsr.getLong(mCsr.getColumnIndex(DatabaseHandler.KEY_ID))));

        //
        currentCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            final int position = mCsr.getPosition();
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // Store the checkbox status
                mCheckBoxStates[position] = ((CheckBox) buttonView).isChecked();
                int restore_cursor_position = mCsr.getPosition();
                //Move the Cursor to the respective row
                //NOTE! 1st position in Lisview is 1 but equates to cursor row 0 etc hence -1
                mCsr.moveToPosition(position);
                Toast.makeText(mContext,
                        "You Changed the CheckBox for row " +
                                Integer.toString(position + 1) +
                                " Item is " +
                                mCsr.getString(mCsr.getColumnIndex(DatabaseHandler.KEY_ITEM))
                        ,
                        Toast.LENGTH_SHORT
                ).show();
                //restore the Cursor's position
                mCsr.moveToPosition(restore_cursor_position);
            }
        });
    }

    // get the list of items (the ID's as long) that have been checked.
    public long[] getCheckedRecordIdList() {

        // using ArrayList as we can add as we don't yet know how many
        ArrayList<Long> rva = new ArrayList<>();
        // Just in case save the current position of the Cursor
        int restore_cursor_position = mCsr.getPosition();
        // Loop through the checkbox states
        for (int i=0; i < mCheckBoxStates.length; i++) {
            // If the checkbox reflected as being checked then handle, else ignore it
            if (mCheckBoxStates[i]) {
                // Move to the respective cursor row
                mCsr.moveToPosition(i);
                // get the respective ID and store in the arraylist
                rva.add(mCsr.getLong(mCsr.getColumnIndex(DatabaseHandler.KEY_ID)));
            }
        }
        // Done with the Cursor so re-position it
        mCsr.moveToPosition(restore_cursor_position);

        // Create the long array to be returned
        long[] rv = new long[rva.size()];
        // Populate the long array with the id's from the arraylist
        for (int i=0; i < rva.size(); i++) {
            rv[i] = rva.get(i);
        }
        // return the long[]
        return rv;
    }
}

3) 修改 MainActivity 以使用自定义适配器并获取检查记录列表(显示通过 Toast 选择的编号) - MainActivity.java

  • 更改/添加的行/方法用 标记。

:-

public class MainActivity extends AppCompatActivity {

    DatabaseHandler mDBHandler;
    ListView mListView;
    SimpleCursorAdapter mSCA;
    MyCustomCursorAdapter mMCA; // <<<<<
    Cursor mCsr;
    Button mDoItButton;
    Context mContext; //<<<<<
    long[] mCheckedIdList; //<<<<<

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        mListView = (ListView) this.findViewById(R.id.lv001); // Get the ListView from it's id
        mDoItButton = (Button) this.findViewById(R.id.doitbutton); //<<<<<
        mDBHandler = new DatabaseHandler(this); // Get an instance of the Database Handler

        // Add some data but only if there is no data
        if (DatabaseUtils.queryNumEntries(mDBHandler.getWritableDatabase(),DatabaseHandler.TABLE_RECORDS) < 1) {

            mDBHandler.insertRecord(100,"Rock","A large stone.","31/12/2017");
            mDBHandler.insertRecord(50,"Boulder","A Rock.","31/12/2018");
            mDBHandler.insertRecord(322,"Soil","Loose earth.","31/7/2015");
            mDBHandler.insertRecord(237,"Stone","A small rock.","31/8/2014");
            mDBHandler.insertRecord(32,"Pebble","A small smooth stone.","11/12/2017");
        }
        mDBHandler.increasePrice(1,213);

        // get all rows into a Cursor
        mCsr = mDBHandler.getAllRecords();

        // Prepare a list of the columns to get the data from, for the ListViewt
        String[] columns_to_get_data_from = new String[]{
                DatabaseHandler.KEY_ID,
                DatabaseHandler.KEY_PRICE,
                DatabaseHandler.KEY_ITEM,
                DatabaseHandler.KEY_DETAILS,
                DatabaseHandler.KEY_DATE
        };

        // Prepare a list of the Views into which to place the data
        int[] itemviews_to_place_data_in = new int[]{
                R.id.record_id,
                R.id.record_price,
                R.id.record_item,
                R.id.record_details,
                R.id.record_date
        };

        // get and instance of SimpleCursorAdapter the listviewitem_record layout
        mSCA = new SimpleCursorAdapter(this,
                R.layout.listviewitem_record,
                mCsr,
                columns_to_get_data_from,
                itemviews_to_place_data_in,
                0);
        // Tie the adapter to the Listview
        mListView.setAdapter(mSCA);

        // <<<<<< Alternate Custom Cursor Adapter
        mMCA = new MyCustomCursorAdapter(this,
                R.layout.listviewitem_record,
                mCsr,
                columns_to_get_data_from,
                itemviews_to_place_data_in,
                R.id.record_checkbox //<<<<<< id of the checkbox
        );
        // Hijack the Listview
        mListView.setAdapter(mMCA); //<<<<<<

        // <<<<< DO IT BUTTON HANDLER i.e. get list of ID's for checked items
        mDoItButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // get the ID's for the checked Items
                mCheckedIdList = mMCA.getCheckedRecordIdList();
                Toast.makeText(mContext,"You have " + mCheckedIdList.length + " Items checked.",Toast.LENGTH_SHORT).show();
            }
        });

    }
}
  • 注意!您通常不会有两个适配器,但我将 SimpleCursorAdapter 留在了比较中。

  • 注意!有点耐心,如果你点击太多太快你可能会感到困惑。

注意!请参阅其他答案以删除选中的项目。

【讨论】:

  • 谢谢!!!!但是我遇到了一些问题。为什么我在 STRING 上没有得到日期,而只有在 DETIALS 中输入的日期?像这样:link。我怎么知道你给我的东西和适配器手册
  • @MenachemYarhi 你有values.put(KEY_DATE, record.getDetails()); // Contact Phone Number,而不是values.put(KEY_DATE, record.getDate()); // Contact Phone Number 在你的addRecord 方法中。
  • 然后。如何将您带给我的东西与适配器手册联系起来? @MikeT
  • 您创建了自定义光标适配器类,然后基于自定义适配器而不是基于 SimpleCursorAdaoter 的 mSCA。例如假设您的 CustomAdapter 是 MyCustomCursorAdapter,您使用 MyCustomCursorAdapter = mSCAmSCA = new MyCustomCursorAdapter(.....。如果我有时间,我可能会用一个例子来更新这个问题。
  • @MenachemYarhi 答案已与自定义适配器以及复选框处理一起添加。非常感谢您将此问题标记为已回答并点击它为有用,如果您发现它有用的话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 2017-07-11
  • 2020-03-22
相关资源
最近更新 更多