У меня есть ListView с собственным макетом и CustomCursorAdapter. Каждая строка имеет свой собственный флажок. Итак... абсолютно ясно, что во время свитки флажки теряют свои состояния. Единственное, что я нашел, это Android сохранить состояние флажка в ListView с помощью адаптера курсора, но ответа там нет. И еще один вопрос. У меня была такая же проблема с моим CustorArrayAdapter. Я решил эту проблему, используя SparseBooleanArray, чтобы сохранить состояния флажков. Он работает нормально, но каждый свиток вызывает onCheckedChanged. Это нормально? Сделка - это мое представление списка, описывающее элементы тревоги и периодические вызовы (onCheckedChanged), запускает/останавливает аварийные сигналы. Много необузданных действий.
Android: CursorAdapter, ListView и CheckBox
Ответ 1
Есть несколько проблем с ListView при наличии проверяемых элементов. Я бы предложил следующую ссылку:
http://tokudu.com/2010/android-checkable-linear-layout/
Я думаю, что это близко к тому, что вы хотите.
Ответ 2
У меня была аналогичная проблема с моей ListView
с CheckBox
и что я сделал, чтобы избавиться от проблемы:
- Создайте ArrayList из Boolean Object, чтобы сохранить состояние каждого CheckBox
- Инициализирует элементы ArrayList до значения по умолчанию
false
, означает, что CheckBox еще не проверен. - Когда вы нажимаете CheckBox. Установите проверку на состояние Проверено/Непроверено и сохраните это значение в ArrayList.
- Теперь установите эту позицию в CheckBox, используя метод setChecked().
Смотрите этот фрагмент кода:
public class MyDataAdapter extends SimpleCursorAdapter {
private Cursor c;
private Context context;
private ArrayList<String> list = new ArrayList<String>();
private ArrayList<Boolean> itemChecked = new ArrayList<Boolean>();
// itemChecked will store the position of the checked items.
public MyDataAdapter(Context context, int layout, Cursor c, String[] from,
int[] to) {
super(context, layout, c, from, to);
this.c = c;
this.context = context;
for (int i = 0; i < this.getCount(); i++) {
itemChecked.add(i, false); // initializes all items value with false
}
}
public View getView(final int pos, View inView, ViewGroup parent) {
if (inView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inView = inflater.inflate(R.layout.your_layout_file, null);
}
final CheckBox cBox = (CheckBox) inView.findViewById(R.id.bcheck); // your
// CheckBox
cBox.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v.findViewById(R.id.your_checkbox_id);
if (cb.isChecked()) {
itemChecked.set(pos, true);
// do some operations here
} else if (!cb.isChecked()) {
itemChecked.set(pos, false);
// do some operations here
}
}
});
cBox.setChecked(itemChecked.get(pos)); // this will Check or Uncheck the
// CheckBox in ListView
// according to their original
// position and CheckBox never
// loss his State when you
// Scroll the List Items.
return inView;
}}
Ответ 3
Я тоже сталкивался с подобной проблемой, поэтому после многих чтений я решил эту проблему следующим образом:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.listview, null);
holder = new ViewHolder();
holder.nameView = (TextView)convertView.findViewById(R.id.textView1);
holder.numberView = (TextView)convertView.findViewById(R.id.textView2);
holder.cb = (CheckBox)convertView.findViewById(R.id.checkBox1);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.nameView.setText(mData.get(position).toString());
holder.numberView.setText(mNumber.get(position).toString());
holder.cb.setChecked(false);
holder.cb.setTag(position);
if(selected.indexOf(mNumber.get(position).toString()) >= 0)
{
holder.cb.setChecked(true);
}
return convertView;
}
}
Вот что я делаю, что на getView() Я снимаю все флажки и проверяю вручную вручную те, которые мне нужно проверить в соответствии с текстовым отображением, которое ему соответствует. Поэтому, если пользователь прокручивается вниз после проверки первого флажка, все флажки в представлении будут сняты, и если он снова прокрутится вверх, тогда все флажки будут сняты, но затем тот, который он нажал, снова будет перепроверен.
Ответ 4
Я решил попробовать с помощью метода setViewBinder. Состояние "Мои учетные записи" хранится в SparseBooleanArray. Состояние кнопки изменяется, когда вы нажимаете флажок самостоятельно и на всю ячейку.
Моя строка: | TextView | CheckBox |
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ..
private SparseBooleanArray checkedItems = new SparseBooleanArray(); //for storing item state
startManagingCursor(cursor);
String[] from = new String[] { dbAdapter.COLUMN_NAME, dbAdapter.COLUMN_CHECK };
int[] to = new int[] { R.id.item_name, R.id.item_check };
recordsAdapter = new SimpleCursorAdapter(this, R.layout.items, cursor, from, to);
recordsAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (columnIndex == 2) { //2 - R.id.item_check
final CheckBox cb = (CheckBox) view;
final int rowID = cursor.getInt(0); //cursor.getInt(0) - _id from table
if (checkedItems.indexOfKey(rowID) >= 0) { //checkedItems contains rowID?
cb.setChecked(checkedItems.get(rowID));
} else if (cursor.getInt(2) > 0) { //cursor.getInt(2): 0 - false, 1 - true
checkedItems.append(rowID, true);
cb.setChecked(true);
} else {
cb.setChecked(false);
}
cb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (checkedItems.indexOfKey(rowID) >= 0) {
checkedItems.put(rowID, !(checkedItems.get(rowID)));
} else {
checkedItems.append(rowID, true);
}
cb.setChecked(checkedItems.get(rowID));
dbAdapter.updateItem(rowID, checkedItems.get(rowID)?1:0);
}
});
return true;
}
return false;
}
});
itemsList.setAdapter(recordsAdapter);
itemsList.setOnItemClickListener(this);
// ..
}
//if click on TextView of row - CheckBox of row is set/unset
@Override
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
TextView tv = (TextView) view.findViewById(R.id.item_name);
ViewGroup row = (ViewGroup) tv.getParent();
CheckBox cb = (CheckBox) row.getChildAt(1);
cb.performClick();
}
Ответ 5
Я не могу понять, почему невозможно (как в HTML) определить объект ViewElement как массив в XML. То есть:.
<CheckBox
android:id="@+id/myCheckBox[]"
android:focusable="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
и сохраните значение int it [true | false]. Это сделало бы жизнь намного проще, вместо того, чтобы использовать сложный исходный фрик. Также данные (т.е. При переключении с пейзажа на портрет) должны храниться андроидом и не теряться.
Возможно, в API 117, версия toothscratch...
Ответ 6
(sry, еще не могу комментировать) - в отношении ответа Викаса Патидара, который работает для меня - будьте внимательны при использовании async-загрузки (например, с помощью Loader), потому что getCount в конструкторе адаптера будет равен нулю.
В результате вы получаете ошибки индексирования (заставляет ArrayList никогда не заполняться). Используйте SparseBooleanArray вместо ArrayList, и он также будет работать с асинхронной загрузкой.
Ответ 7
Возможно, здесь будет поздно, чтобы добавить ответ Викаса Патидара, это полная реализация с использованием метода bindView
для тех из вас, кто подает иск в CursorAdapter:
@Override
public void bindView(View view, Context context, Cursor cursor) {
final ViewHolder holder = (ViewHolder) view.getTag();
final int position = cursor.getPosition();
String name = (cursor.getString(cursor.getColumnIndexOrThrow("NotificationDateFor")));
String image = cursor.getString(cursor.getColumnIndexOrThrow("imageUri"));
System.out.println("cursor.getPosition(test): "+cursor.getPosition());
holder.nametext.setText(name);
// setImage(image, holder.iv);
holder.chk.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
if (holder.chk.isChecked()) {
itemChecked.set(position, true);
System.out.println("cursor.getPosition(true): "+position);
} else if (!holder.chk.isChecked()) {
itemChecked.set(position, false);
System.out.println("cursor.getPosition(false): "+position);
// AddDelete
}
}
});
holder.chk.setChecked(itemChecked.get(cursor.getPosition()));
}
Примечание: final int position = cursor.getPosition();
значим!
Ответ 8
Вы можете сэкономить много хлопот, используя режим просмотра в режиме множественного выбора Listview.
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);