#java #android #sqlite #android-layout
#java #Android #sqlite #android-макет
Вопрос:
Я пытаюсь сделать рабочий флажок внутри ListView. Макет просто main.xml который показывает несколько row.xml когда новая информация добавляется в базу данных sqlite. Я могу сделать рабочий флажок в main.xml , но я не знаю, как сделать рабочий флажок внутри 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);
}
Флажок 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», потому что, если это не 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;
}
Флажок сверху, который проверяется на экране, является рабочим флажком (checkboxmain1), который добавляет «1» в базу данных
Есть ли какой-либо способ сделать ответ флажков в ListView?
Ответ №1:
Ниже приведен относительно простой способ обработки событий щелчка просмотров внутри элемента ListView.
Чтобы просто получить фактический элемент, на который был нажат, чтобы отличить его от другого элемента, вам нужен пользовательский адаптер, в данном случае пользовательский адаптер курсора, в котором вы можете установить для тега представления соответствующее значение (идентификатор).
В сочетании с этим вы используете атрибут onClick, чтобы указать метод, который будет вызываться при нажатии на view (флажок), который определен в Activity.
Ниже приведен рабочий пример, основанный на вашем коде. Он использует более простой и гибкий метод для управления 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>
- Обратите внимание на изменения, внесенные в флажок
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
);
}
}
}
- Обратите внимание, что это может быть по-другому, оно было создано для тестирования.
Результат
Ниже приведен снимок экрана, сделанный после нажатия нескольких флажков, чтобы отображался тост :-
И скриншот после перезапуска приложения (показывающий, что состояние сохранено, т. Е. База данных обновлена в соответствии с флажками) :-
Комментарии:
1. Я записал ваши изменения в свой код, и это работает! Большое спасибо вам! Вечером я изучу эти изменения, чтобы понять больше кода 🙂 . Хорошего дня!