java - 如何在 ListView 中创建工作复选框(其中包含来自 sqlite 数据库的项目)

标签 java android sqlite android-layout

我正在尝试在 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;
}

screen

屏幕上选中的顶部复选框正在工作 CheckBox (checkboxmain1),它将“1”添加到数据库

有没有办法让ListView中的CheckBox做出响应?

最佳答案

下面是处理 ListView 的 Item 中 View 的单击事件的相对简单的方法。

要简单地获取已单击的实际项目以将其与另一个项目区分开来,您需要一个自定义适配器,在本例中是一个自定义光标适配器,您可以在其中将 View 的标签设置为适当的值(id)。

与此结合,您可以使用 onClick 属性来指定单击 View (复选框)时要调用的方法,该方法在 Activity 中定义。

以下是基于您的代码的工作示例。它使用更简单、更灵活的方法来管理 ListView,即 ma​​nageListView

请注意,为了方便起见,您的一些代码已被省略(注释掉)。

代码

行.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 :-

enter image description here

以及重新启动应用程序后的屏幕截图(显示状态已保留,即根据复选框更新数据库):-

enter image description here

关于java - 如何在 ListView 中创建工作复选框(其中包含来自 sqlite 数据库的项目),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55559414/

相关文章:

java - MenuInflater 究竟是如何工作的?

Java泛型问题

android - Kotlin 使用 Parcelable 将 ListArray 传递给另一个 Activity

sqlite - 如何将 SQLite 中的当前时间戳存储为滴答?

sql - 对于相同的查询,SQLite命令行客户端和SQLite库之间的性能不同

sql - 从SQLite中的表中选择模式

java - 使用正则表达式捕获/包含并在之后选择字符

java - 请解释为什么在 Cpp、Java 和 C# 中允许或不允许将 List<A> 转换为 List<A.super>

android - 如何在 Android 中将值从一个 Activity 传递到另一个 Activity?

java - Android NoSuchElementException 和扫描仪