0

I have a table in DataBase, and I want to make a table. Now it makes no sense that I will do a lot of CheckBox and show you only some of them according to the information in the table. I heard about the But how do I do of I found an example of on the Internet and when I tried to insert large information, only half the information came in, so I was told to do . Do you have an example of how to do this?

It DatabaseHandler:

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();
    }
}
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Menachem Yarhi
  • 63
  • 3
  • 11

2 Answers2

2

Deletion of checked Items as per I want to erase the lines I have marked.

This is relatively simple to progress to.

It involves - a) adding a method to the database helper to delete according to id. - b) (i)amend the onClick listener to invoke the delete method (simple loop) and to then (ii)update the listview (after the loop).

However, the original custom adapter has some flaws in that the original cursor is retained via mCsr and no consideration was given to the number of checkboxes being changed when the Cursor is changed (swapped).

As such the adapter has had references to mCsr removed and replaced by the Cursor passed or via calling the getCursor method. Also the swapCursor() method has been overidden to adjust the number of elements of and re-initialise the elemnets (set to false), of mCheckBoxes.

a) The new deleteRecord method :-

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 amendments (note includes grouping all deletes into a single transaction) :-

    // <<<<< 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) Update the Listview (new method in the Activity) :-

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

Notes

  • this is added as a method to the activity.
  • mMCA.notifyDatasetChanged(); is an alternative (I personally prefer `swapCursor1 as it's more decsriptive).

The modified Custom Cursor Adapter should be :-

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);
    }
}
MikeT
  • 51,415
  • 16
  • 49
  • 68
  • Could you please advise on where is getCheckedRecordIdList() getting called ? – Guri S Dec 05 '18 at 19:53
  • Also my checkBoxStates are not getting saved ? Is there are way to do that ? – Guri S Dec 05 '18 at 19:59
  • In the **Do It** button's onClickListener, See **b(i)** in the asnwer i.e. by **`mCheckedIdList = mMCA.getCheckedRecordIdList();`** – MikeT Dec 05 '18 at 20:02
  • You could add a new column to the table along with methods to handle the check box status. – MikeT Dec 05 '18 at 20:09
1

here's an example based upon you code.

1) The Activity's layout (i.e a ListView with an id of lv001) as file 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) A layout for each row (Item in ListView terminology) as file 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>
  • Note! the inclusion of a CheckBox, as well as TextViews for all columns.

3) To simplify matters I used this as 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();
    }
    */
}

Notes about Changes to DatabaseHandler.java

  • The rowid alias has been changed from ID to _id, this is because CursorAdapter's need a column named _id and that column should be an alias for for the rowid (not going into technicalities here).

  • Instead of using a Record class I've commented out your code that uses this class, for my convenience.

  • I've changed TABLE and COLUMN names definitions to public, so they can be accessed elsewhere.

  • I've added two new methods insertRecord and getAllRecords:-

    • insertRecord just to add some data for testing/example
    • getAllRecords retrieves all rows as a Cursor, as opposed to an array.
    • NOTE! The database is not closed, this would result in an exception because a Cursor needs access to the database (opening and closing a database can be detrimental anyway).

4) The Activity itself (just displays the ListView after adding some data for the first run) as file 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);
    }
}

Result :-

enter image description here

Notes

This doesn't go into handling the checkboxes, this would likely need a CustomAdapter. There's plenty of tutorials for that e.g. how do i create a custom cursor adapter for a listview for use with images and text?.

Edit Amended to Include CheckBox handling

1) The Activity's layout activity_main.xml - Added a Button for getting Checked Items :-

<?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) The Custom Cursor Adapter MyCustomCursorAdapter.java

  • Signature similar to SimpleCursorAdapter BUT with an extra parameter for the id of the CheckBox.
  • Includes method getCheckedRecordIdList, which will return a list of Id's that have been checked.
  • Issues a Toast when a checkbox is checked or unchecked which displays the item, as in the ListView's Item # (not the Item in the table), clicked and the Item clicked (as in the Item value from the table).

:-

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) The amended MainActivity to use the Custom Adapter and to get the list of checked Records (displays number selected via Toast) - MainActivity.java

  • Changed/Added Lines/Methods are marked with <<<<<.

:-

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();
            }
        });

    }
}
  • Note! you wouldn't typically have two adapters, but I left the SimpleCursorAdapter in for comparison.

  • Note! be a little patient, as if you click too much too soon you may get consfused.

Note! See other answer for deleting checked items.

MikeT
  • 51,415
  • 16
  • 49
  • 68
  • Thank you!!!! But there are some problems I've encountered. Why do not I get a date on STRING but only what's entered in DETIALS? like this: [link](https://imgur.com/a/t3JcV) . and how am i aouthor what you give me and The ADAPTER manual – Menachem Yarhi Nov 29 '17 at 14:57
  • @MenachemYarhi you have `values.put(KEY_DATE, record.getDetails()); // Contact Phone Number`, instead of `values.put(KEY_DATE, record.getDate()); // Contact Phone Number` in your `addRecord` method. – MikeT Nov 29 '17 at 19:10
  • Thenks. How do I connect what you have brought me with the adapter manual? @MikeT – Menachem Yarhi Nov 29 '17 at 22:25
  • You create your Custom Cursor Adapter class and then instead of mSCA being based upon a SimpleCursorAdaoter you based it on the CustomAdapter. e.g. assuming you CustomAdapter is MyCustomCursorAdapter you use `MyCustomCursorAdapter = mSCA` along with `mSCA = new MyCustomCursorAdapter(.....`. I may update the question with an example if I get the time. – MikeT Nov 30 '17 at 01:58
  • @MenachemYarhi Answer has been added along with Custom Adapter along with CheckBox handling. I'd appreciate you marking this question as answered and also clicking it as being useful, if you found it useful. – MikeT Nov 30 '17 at 05:02
  • @MenachemYarhi that's because you are using a Radio button instead of a CheckBox. You either need to use a CheckBox in the Item layout or amend the Adapter to handle a radio button/radio group combination. The latter being more complicated as you then have to determine which RadioButton was selected in the RadioGroup. If it's just a single on/off then CheckBox would be more suitable. – MikeT Dec 02 '17 at 23:07
  • Yes, I noticed and deleted the message. Thank you! But I got caught up in a small error that when I want to use the ID of what was marked in CHECKBOX it does not work for me. I want to erase the lines I have marked. That's what I tried. And when I do not use ID what CHECKBOX it erases me what I want
           int x=mCheckedIdList.length;
    
                  while (mCheckedIdList.length<0)
    {
        String II =String.valueOf((int)mCheckedIdList[x]);
    
    x--;
    }
    x=5;
                    String II ="5";
    db.deleteNote( II);
    
                    finish();
                    startActivity(getIntent());
    – Menachem Yarhi Dec 03 '17 at 00:35
  • @MenachemYarhi Amended the answer to show you how to do the deletions. – MikeT Dec 03 '17 at 01:21
  • @MenachemYarhi note the above has a flaw(s) due to values being retained and thus subsqeuent deletion attempts are based upon old values. Edit 3 - is more suitable when performing deletions. – MikeT Dec 03 '17 at 02:08
  • @MenachemYarhi had to add another answer due to space limitations for edit 3. – MikeT Dec 03 '17 at 02:53
  • Thank you very much for everything !!!!! But I did not understand, no matter how much I tried to figure out how I controlled only one of the list? For example, I want to make the list X be green and the CHECK BOX is hidden and another line is blue. Sorry for the delay. – Menachem Yarhi Dec 25 '17 at 15:47
  • Can you please help me here: https://stackoverflow.com/questions/48065247/the-views-are-crazy-i-use-listview-and-all-views-change ? I did what you told me and it helped me. thank you very much. But I ran into some problems – Menachem Yarhi Jan 02 '18 at 17:38