我正在尝试在 ListView 中创建工作复选框。 布局只是 main.xml,当新信息添加到 sqlite 数据库时,它会显示多个 row.xml。 我可以在 main.xml 中创建工作 CheckBox,但我不知道如何在 row.xml 中创建工作 CheckBox。
AndroidSQLite.java(显示 main.xml 和其中的 row.xml)
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);
}
复选框 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 和 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>
行.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>
(row.xml 中的 checkboxmain2 将 android:focusable 和 android:focusableInTouchMode 设置为“false”,因为如果它不为 false,ListView OnItemClickListener 将无法工作)
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 (checkboxmain1),它将“1”添加到数据库
有没有办法让ListView中的CheckBox做出响应?
最佳答案
下面是处理 ListView 的 Item 中 View 的单击事件的相对简单的方法。
要简单地获取已单击的实际项目以将其与另一个项目区分开来,您需要一个自定义适配器,在本例中是一个自定义光标适配器,您可以在其中将 View 的标签设置为适当的值(id)。
与此结合,您可以使用 onClick 属性来指定单击 View (复选框)时要调用的方法,该方法在 Activity 中定义。
以下是基于您的代码的工作示例。它使用更简单、更灵活的方法来管理 ListView,即 manageListView
请注意,为了方便起见,您的一些代码已被省略(注释掉)。
代码
行.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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="ListViewCheckBoxHanlder"/>
</LinearLayout>
- 注意对复选框所做的更改
activity_main.xml
<?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>
AndroidSQLite.java
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();
}
}
- 请注意,一些注释掉的代码已被替换,一些代码为了方便而被注释掉。
MyCursorAdapter.java
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
}
}
- 请注意,上面是一个新类。
SQliteAdapter.java
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;
}
}
- 请注意,这很可能有所不同,它是为了满足测试而创建的。
SQLiteHelper.java
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
);
}
}
}
- 请注意,这很可能有所不同,它是为了满足测试而创建的。
结果
以下是单击多个复选框后拍摄的屏幕截图,以便显示 Toast :-
以及重新启动应用程序后的屏幕截图(显示状态已保留,即根据复选框更新数据库):-
关于java - 如何在 ListView 中创建工作复选框(其中包含来自 sqlite 数据库的项目),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55559414/