Как заставить работать CheckBox внутри ListView (который содержит элементы из базы данных sqlite) - PullRequest
0 голосов
/ 07 апреля 2019

Я пытаюсь заставить работать CheckBox внутри ListView.Layout - это просто main.xml, который показывает несколько строк.xml при добавлении новой информации в базу данных sqlite.Я могу заставить работать CheckBox в main.xml, но я не знаю, как заставить работать CheckBox внутри row.xml.

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

}

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 и 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 из row.xml есть android: focusable и android: focusableInTouchMode установлен в «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 сверху, которыйпроверено на экране работает CheckBox (checkboxmain1), который добавляет «1» в базу данных

Есть ли способ сделать ответ CheckBoxes в ListView?

1 Ответ

2 голосов
/ 08 апреля 2019

Ниже приведен сравнительно простой способ обработки событий щелчков представлений в элементе ListView.

Чтобы просто получить фактический элемент, по которому был выполнен щелчок, чтобы отличить его от другого элемента, необходим специальный адаптерв этом случае пользовательский адаптер курсора, в котором вы можете установить для тега представления соответствующее значение (идентификатор).

В сочетании с этим вы используете onClick *Атрибут 1008 * для указания метода, который будет вызываться при нажатии на представление (флажок), что определено в Упражнении.

Ниже приведен рабочий пример на основе вашего кода.Он использует более простой и гибкий метод управления ListView, т. Е. manageListView

Обратите внимание, что для удобства часть вашего кода была опущена (закомментирована).

Код

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:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="ListViewCheckBoxHanlder"/>
</LinearLayout>
  • Обратите внимание на изменения, внесенные в CheckBox

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
            );
        }
    }
}
  • Обратите внимание, что это может быть иным, он был создан для обслуживания для тестирования.

Результат

Ниже приведен скриншот, сделанный после нажатия нескольких флажков, чтобы отобразился тост:-

enter image description here

и снимок экрана после перезапуска приложения (показывающий, что состояние сохранено, т.е. база данных обновлена ​​в соответствии с флажками): -

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...