Я пытаюсь просто сделать щелкнутые элементы ListView для изменения фона. Но мне кажется, что на самом деле это невозможно. есть много сообщений с примерами этого, но ни один из них не работает надежно. Как я понял - это как-то связано с "утилизацией".
Я вызываю view.setSelected() в OnItemClickListener адаптера, и он прекрасно применяет другой фон к выбранному элементу в соответствии с моими настройками. Но когда я выбираю элемент, из-за которого в ListView не хватает места (не важно, как именно), и полоса прокрутки появляется (или исчезает) внутри ListView - Android забывает мой выбор, и применяется стиль по умолчанию. Та же ошибка возникает при повороте экрана - элемент отменяет выбор. Поэтому я думаю, что «отмена выбора» происходит во время вызова адаптера getView().
Интересно, что мое событие onClick вызывает отправку запроса json в фоновую службу, а также получение и декодирование ответа json, поэтому между щелчком элемента и изменением содержимого действия требуется некоторое время. Вот как это выглядит:
- Я щелкаю элемент ListView. Он меняет фон на «выбранный цвет».
- Несколько мгновений жду.
- Содержание активности меняется в соответствии с ответом службы. Полоса прокрутки появляется внутри ListView. Фон элемента меняется на «цвет по умолчанию» (элемент не выбран).
Нажатие на элементы, которые не вызывают появление полосы прокрутки, работает хорошо - выбранные элементы не отменяются после обработки ответа службы.
Попытка вызвать setSelected() внутри getView() адаптера не влияет на ошибку. Элемент по-прежнему не выбран. Пробовал задавать фон элемента вручную в getView() - стало интереснее: элементы, вызывающие появление полосы прокрутки, стали работать корректно, а элементы, не вызывающие появление полосы прокрутки (на самом деле это означает, что они не вызывают вызов getView()) перестал работать!
Весь код достаточно сложен, поэтому я выложу лишь некоторые важные фрагменты. Вот мой OnItemClickListener:
private AdapterView.OnItemClickListener onCategoryClickListener =
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, final View view, final int position,
long id) {
categoriesAdapter.setSelectedPosition(position);
view.setSelected(true);
// More code here
}
};
и вот фрагмент кода моего адаптера:
private int selectedPosition;
private boolean selectable = true;
public void setSelectedPosition(int position) {
this.selectedPosition = position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView label = (TextView) View.inflate(context, textViewResourceId, null);
label.setText(getName(values.get(position)));
if(selectable) {
label.setBackgroundResource(R.drawable.list_selector);
if(position == selectedPosition) {
label.setSelected(true); // This does not work. Why?
label.setBackgroundColor( // This gives strange results
context.getResources().getColor(R.color.list_item_selected_color));
} else {
// Similar code here, but for deselecting items.
}
}
return label;
}
и вот мой селектор:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@color/list_item_default_color"
android:state_selected="false" />
<item
android:drawable="@color/list_item_selected_color"
android:state_selected="true"/>
</selector>
Я много искал, как заставить его работать, но ничего не помогает. Вот некоторые вещи, которые я пробовал:
- Запуск view.setSelected() внутри view.post()
- Запуск list.setSelection() - для чего этот метод? это ничего не делает!
- Инициализация TextView более точная, проверка, является ли convertView значением null. Дает плохие, очень плохие результаты - вызывает перемешивание элементов ListView (без какого-либо влияния на их статус выбора).
- Не использовал ViewHolder, потому что у меня нет сложных макетов для Item, у меня есть простой TextView.