Reputation: 19
I'm trying to make working CheckBox inside ListView. Layout is just main.xml which shows multiple row.xml when new information is added to sqlite database. I can make working CheckBox in main.xml, but I don't know how to make working CheckBox inside row.xml.
AndroidSQLite.java (shows main.xml, and row.xml inside it)
public class AndroidSQLite extends Activity {
(...)
checkBoxMain = (CheckBox)findViewById(R.id.checkboxmain1);
listContent = (ListView)findViewById(R.id.contentlist);
mySQLiteAdapter = new SQLiteAdapter(this);
mySQLiteAdapter.openToWrite();
cursor = mySQLiteAdapter.queueAll();
String[] from = new String[]{SQLiteAdapter._id,
SQLiteAdapter.KEY_NAME,
SQLiteAdapter.KEY_QUANTITY,
SQLiteAdapter.KEY_CHECKED};
int[] to = new int[]{R.id.id, R.id.name, R.id.quantity,
R.id.checkboxmain};
cursorAdapter =
new SimpleCursorAdapter(this, R.layout.row, cursor, from,
to);
listContent.setAdapter(cursorAdapter);
listContent.setOnItemClickListener(listContentOnItemClickListener);
buttonAdd.setOnClickListener(buttonAddOnClickListener);
checkBoxMain.setOnClickListener(onCheckboxClicked);
}
CheckBox OnClickListener (AndroidSQLite.java)
CheckBox.OnClickListener onCheckboxClicked
= new CheckBox.OnClickListener() {
public void onClick(View v) {
CheckBox checkBoxMain = (CheckBox)
findViewById(R.id.checkboxmain1);
boolean checked = checkBoxMain.isChecked();
if (checked) {
Boolean data1 = checkBoxMain.isChecked();
mySQLiteAdapter.insertChecked(data1);
updateList();
}
}
};
ListView OnItemClickListener (AndroidSQLite.java)
private ListView.OnItemClickListener listContentOnItemClickListener
= new ListView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, int
position,
long id) {
Cursor cursor = (Cursor) parent.getItemAtPosition(position);
final int item_id =
cursor.getInt(cursor.getColumnIndex(SQLiteAdapter._id));
String item_name =
cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_NAME));
String item_quantity =
cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_QUANTITY));
AlertDialog.Builder myDialog
= new AlertDialog.Builder(AndroidSQLite.this);
// when item in row.xml is clicked alertdialog is shown
// code of AlertDialog
myDialog.show();
}};
onDestroy and updateList() (AndroidSQLite.java)
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
mySQLiteAdapter.close();
}
private void updateList(){
cursor.requery();
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/panelup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LIST SQ1"
/>
<ListView
android:id="@+id/contentlist"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/panelup"
android:layout_above="@id/paneldown"/>
<CheckBox
android:id="@+id/checkboxmain1"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/paneldown"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<EditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
<EditText
android:id="@+id/quantity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
/>
<Spinner
android:id="@+id/mu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/mu_values"
android:layout_weight="2"
/>
<Button
android:id="@+id/add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="+"
/>
</LinearLayout>
</RelativeLayout>
row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/layoutmain"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:padding="2dip"
android:text="M"/>
<TextView
android:id="@+id/id"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:padding="2dip"
android:paddingRight="10dip"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:padding="2dip"
android:paddingRight="10dip"
android:text="-" />
<TextView
android:id="@+id/name"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="2dip"/>
</LinearLayout>
<TextView
android:id="@+id/quantity"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="2dip"/>
<CheckBox
android:id="@+id/checkboxmain2"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
(checkboxmain2 from row.xml have android:focusable and android:focusableInTouchMode set on "false" because if it's not false, ListView OnItemClickListener it's notr working)
SQLiteAdapter.java
public class SQLiteAdapter {
(...)
public SQLiteAdapter openToWrite() throws android.database.SQLException {
sqLiteHelper = new SQLiteHelper(context, MYDATABASE_NAME, null,
MYDATABASE_VERSION);
sqLiteDatabase = sqLiteHelper.getWritableDatabase();
return this;
}
public void close(){
sqLiteHelper.close();
}
public long insertChecked(boolean data1){
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_CHECKED, data1);
return sqLiteDatabase.insert(MYDATABASE_TABLE, null, contentValues);
}
public Cursor queueAll(){
String[] columns = new String[]{_id, KEY_NAME, KEY_PRICE,
KEY_QUANTITY, KEY_MU,
KEY_PDATE, KEY_SHOP, KEY_CHECKED};
Cursor cursor = sqLiteDatabase.query(MYDATABASE_TABLE, columns,
null, null, null, null, null);
return cursor;
}
CheckBox on top, which is checked on screen is working CheckBox (checkboxmain1) which adds "1" to database
Is there any way to make response of CheckBoxes in ListView?
Upvotes: 0
Views: 84
Reputation: 57043
The following is a relatively simple way of handling click events of views within an Item of a ListView.
To simply obtain the actual item that has been clicked to distinguish it from another Item you need a Custom Adapter, in this case a Custom Cursor Adapter, in which you can set the view's tag to an appropriate value (the id).
In conjunction with this you use the onClick attribute to specify the method to be called when the view (checkbox) is clicked, which is defined in the Activity.
The following is a working example based upon your code. It uses a simpler and more flexible method for managing the ListView i.e. manageListView
Note some of your code has been omitted (commented out) for convenience.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/layoutmain"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:padding="2dip"
android:text="M"/>
<TextView
android:id="@+id/id"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:padding="2dip"
android:paddingRight="10dip"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:padding="2dip"
android:paddingRight="10dip"
android:text="-" />
<TextView
android:id="@+id/name"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="2dip"/>
</LinearLayout>
<TextView
android:id="@+id/quantity"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="2dip"/>
<CheckBox
android:id="@+id/checkboxmain2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="ListViewCheckBoxHanlder"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/panelup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LIST SQ1"
/>
<ListView
android:id="@+id/contentlist"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/panelup"
android:layout_above="@id/paneldown"/>
<CheckBox
android:id="@+id/checkboxmain1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/paneldown"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<EditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
<EditText
android:id="@+id/quantity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
/>
<Spinner
android:id="@+id/mu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/mu_values"
android:layout_weight="2"
/>
<Button
android:id="@+id/add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="+"
/>
</LinearLayout>
</RelativeLayout>
public class AndroidSQLite extends AppCompatActivity {
CheckBox checkBoxMain;
ListView listContent;
Button buttonAdd;
Cursor cursor;
SQLiteAdapter mySQLiteAdapter;
//SimpleCursorAdapter cursorAdapter; //<<<<<<<<<< NOT USED ANYMORE
MyCursorAdapter myadapter; //<<<<<<<<<< Use a custom adapter that sets the tag of the checkbox to the respective id
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkBoxMain = (CheckBox)findViewById(R.id.checkboxmain1);
listContent = (ListView)findViewById(R.id.contentlist);
mySQLiteAdapter = new SQLiteAdapter(this);
mySQLiteAdapter.openToWrite();
manageListView(); //<<<<<<<<<< ADDED
/* !!!!!!!!! COMMENTED OUT
cursor = mySQLiteAdapter.queueAll();
String[] from = new String[]{SQLiteAdapter._id,
SQLiteAdapter.KEY_NAME,
SQLiteAdapter.KEY_QUANTITY,
SQLiteAdapter.KEY_CHECKED};
int[] to = new int[]{R.id.id, R.id.name, R.id.quantity,
R.id.checkboxmain2};
cursorAdapter =
new SimpleCursorAdapter(this, R.layout.row, cursor, from,
to,0);
listContent.setAdapter(cursorAdapter);
listContent.setOnItemClickListener(listContentOnItemClickListener);
*/
//buttonAdd.setOnClickListener(buttonAddOnClickListener); //<<<<<<<<<<< you want this back in
}
//<<<<<<<<<< ADDED >>>>>>>>>>
@Override
protected void onResume() {
super.onResume();
manageListView(); //Refresh the List when resuming e.g. returning from another activity
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
cursor.close(); //<<<<<<<<<< SHOULD ALWAYS CLOSE CURSOR
mySQLiteAdapter.close();
}
//<<<<<<<<<< NO LONGER USED >>>>>>>>>>
private void updateList(){
cursor = mySQLiteAdapter.queueAll();
myadapter.swapCursor(cursor);
}
//<<<<<<<< NOTE NOT USED but you'd want this to be used
CheckBox.OnClickListener onCheckboxClicked
= new CheckBox.OnClickListener() {
public void onClick(View v) {
CheckBox checkBoxMain = (CheckBox)
findViewById(R.id.checkboxmain1);
boolean checked = checkBoxMain.isChecked();
if (checked) {
Boolean data1 = checkBoxMain.isChecked();
mySQLiteAdapter.insertChecked(data1);
manageListView(); //<<<<<<<<<< refresh the ListView
}
}
};
//<<<<<<<<<<NOT USED>>>>>>>>>>
private ListView.OnItemClickListener listContentOnItemClickListener
= new ListView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, int
position,
long id) {
Cursor cursor = (Cursor) parent.getItemAtPosition(position);
final int item_id =
cursor.getInt(cursor.getColumnIndex(SQLiteAdapter._id));
String item_name =
cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_NAME));
String item_quantity =
cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_QUANTITY));
AlertDialog.Builder myDialog
= new AlertDialog.Builder(AndroidSQLite.this);
// when item in row.xml is clicked alertdialog is shown
// code of AlertDialog
myDialog.show();
updateList();
}
};
/**<<<<<<<<<< ADDED >>>>>>>>>>>
* Manage the ListView building from new or refreshing the data
*/
private void manageListView() {
cursor = mySQLiteAdapter.queueAll(); // get the source data (cursor) for the listview
if (myadapter == null) {
myadapter = new MyCursorAdapter(this,cursor);
listContent.setAdapter(myadapter);
} else {
myadapter.swapCursor(cursor);
}
}
/**<<<<<<<<<< ADDED >>>>>>>>>>
* Handle the CheckBox being clicked,
* NOTE set in the layout
* @param v The View
*/
public void ListViewCheckBoxHanlder(View v) {
CheckBox cb = v.findViewById(R.id.checkboxmain2);
Toast.makeText(this, "You clicked the CheckBox for ID " + (String) cb.getTag(), Toast.LENGTH_SHORT).show();
int checked = 0;
if (cb.isChecked()) {
checked = 1;
}
long id = Long.valueOf((String) cb.getTag());
mySQLiteAdapter.updateChecked(id,checked);
manageListView();
}
}
public class MyCursorAdapter extends CursorAdapter {
public MyCursorAdapter(Context context, Cursor c) {
super(context, c, true);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
return v;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.row,parent,false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
//Note Cursor will be positioned appropriately
TextView name = (TextView) view.findViewById(R.id.name);
TextView id = (TextView) view.findViewById(R.id.id);
TextView quantity = (TextView) view.findViewById(R.id.quantity);
CheckBox cb = (CheckBox) view.findViewById(R.id.checkboxmain2);
name.setText(cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_NAME)));
id.setText(cursor.getString(cursor.getColumnIndex(SQLiteAdapter._id)));
quantity.setText(cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_QUANTITY)));
cb.setChecked(cursor.getInt(cursor.getColumnIndex(SQLiteAdapter.KEY_CHECKED)) > 0);
cb.setTag(cursor.getString(cursor.getColumnIndex(SQLiteAdapter._id))); //<<<<<<<<<< SET TAG to the ID
}
}
public class SQLiteAdapter {
SQLiteDatabase sqLiteDatabase;
SQLiteHelper sqLiteHelper;
Context context;
public static final String KEY_CHECKED = "checked";
public static final String _id = BaseColumns._ID;
public static final String KEY_NAME = "name";
public static final String KEY_QUANTITY = "quantity";
public static final String KEY_PRICE = "price";
public static final String KEY_MU = "mu";
public static final String KEY_PDATE = "pdate";
public static final String KEY_SHOP = "shop";
public SQLiteAdapter(Context context) {
this.context = context;
openToWrite();
}
public SQLiteAdapter openToWrite() throws android.database.SQLException {
sqLiteHelper = new SQLiteHelper(context, MYDATABASE_NAME, null,
MYDATABASE_VERSION);
sqLiteDatabase = sqLiteHelper.getWritableDatabase();
return this;
}
public void close() {
sqLiteHelper.close();
}
public long insertChecked(boolean data1) {
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_CHECKED, data1);
return sqLiteDatabase.insert(MYDATABASE_TABLE, null, contentValues);
}
public int updateChecked(long id,int check) {
ContentValues cv = new ContentValues();
cv.put(KEY_CHECKED,check);
String whereclause = _id + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
return sqLiteDatabase.update(MYDATABASE_TABLE,cv,whereclause,whereargs);
}
public Cursor queueAll() {
String[] columns = new String[]{_id, KEY_NAME, KEY_PRICE,
KEY_QUANTITY, KEY_MU,
KEY_PDATE, KEY_SHOP, KEY_CHECKED};
Cursor cursor = sqLiteDatabase.query(MYDATABASE_TABLE, columns,
null, null, null, null, null);
return cursor;
}
}
public class SQLiteHelper extends SQLiteOpenHelper {
public static final String MYDATABASE_NAME = "mydatabase";
public static final int MYDATABASE_VERSION = 1;
public static final String MYDATABASE_TABLE = "mytable";
SQLiteDatabase mDB;
public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,int version) {
super(context, name, factory, version);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
String crt_tbl_sql = "CREATE TABLE IF NOT EXISTS " + MYDATABASE_TABLE + "(" +
SQLiteAdapter._id + " INTEGER PRIMARY KEY, " +
SQLiteAdapter.KEY_NAME + " TEXT, " +
SQLiteAdapter.KEY_SHOP + " TEXT, " +
SQLiteAdapter.KEY_PDATE + " TEXT, " +
SQLiteAdapter.KEY_PRICE + " REAL, " +
SQLiteAdapter.KEY_QUANTITY + " INTEGER, " +
SQLiteAdapter.KEY_MU + " TEXT, " +
SQLiteAdapter.KEY_CHECKED + " INTEGER DEFAULT 0" +
")";
db.execSQL(crt_tbl_sql);
addSomeTestingData(db,10);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
private long addRow(String name, String shop, String pdate, double price, int quantity, String mu, SQLiteDatabase db) {
ContentValues cv = new ContentValues();
cv.put(SQLiteAdapter.KEY_NAME,name);
cv.put(SQLiteAdapter.KEY_SHOP,shop);
cv.put(SQLiteAdapter.KEY_PDATE,pdate);
cv.put(SQLiteAdapter.KEY_PRICE,price);
cv.put(SQLiteAdapter.KEY_QUANTITY,quantity);
cv.put(SQLiteAdapter.KEY_MU,mu);
return db.insert(MYDATABASE_TABLE,null,cv);
}
private void addSomeTestingData(SQLiteDatabase db, int number_to_add) {
for (int i = 0; i < number_to_add;i++) {
String suffix = String.valueOf(i);
String day_in_month = suffix;
if (i < 10) {
day_in_month = "0" + day_in_month;
}
addRow(
"Test" + suffix,
"Shop" + suffix,
"2019-01-" + day_in_month,
10.5 + new Double(i * 3),
i * 4,
"mu" + suffix,
db
);
}
}
}
The following is a screenshot taken after clicking a number of checkboxes so the Toast would be shown :-
And a screenshot after restarting the App (showing that the state has been retained i.e. database updated according to the checkboxes) :-
Upvotes: 2