#android #android-listview
#Android #android-listview
Вопрос:
У меня такое чувство, что это связано с какой-то оптимизацией рендеринга или чем-то еще, но я не уверен, что.
У меня есть представление списка, и когда элемент выбран, я меняю его цвет фона, чтобы он визуально оставался выбранным.
Проблема возникает, когда список выходит за пределы экрана (он прокручивается), если я выбираю элемент вверху, а затем прокручиваю вниз, он также отображает другой выбранный элемент, который когда-то был вне поля зрения (я никогда не вижу 2 выбранных элемента на экране одновременно). Это также работает противоположным образом: если я выберу элемент внизу, а затем прокрутю вверх, он отобразит другой элемент как выбранный.
Также еще одно замечание: расстояние между выбранными элементами неравномерно, если я поворачиваю свое устройство в альбомную ориентацию, расстояние между выбранными элементами меньше.
Если неясно, в чем проблема, я также прикрепил фотографии.
Это с минимальным списком, в нем отображается только один выбранный элемент.
Здесь я выбрал элемент в верхней части.
После прокрутки вниз (см. Полосу прокрутки) отображается другой выбранный элемент.
Теперь для кода.
Фрагмент списка.
public class ResultListFragment extends ListFragment {
BookListAdapter mBooksArray;
BookData api;
View footer;
ListView list;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Activity parent = getActivity();
BookSearch app = (BookSearch) parent.getApplicationContext();
api = app.bookAPI;
mBooksArray = new BookListAdapter(/*some params*/);
mBooksArray.currentActivity = parent;
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
list = (ListView) inflater.inflate(R.layout.search_results, null);
footer = inflater.inflate(R.layout.load_more, null);
return list;
}
public void onActivityCreated( Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
list.addFooterView(footer);
list.setAdapter(mBooksArray);
}
}
И ArrayAdapter, цвет меняется в методе onClick.
public class BookListAdapter extends ArrayAdapter<Book> {
ArrayList<Book> books;
private BookData bookData;
Activity currentActivity;
final BookListAdapter self = this;
private View selected = null;
public void update() {
currentActivity.runOnUiThread(new Runnable() {
public void run() {
self.notifyDataSetChanged();
}
});
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.search_list_view_item, null);
}
/*some code to set the image and text */
v.setOnClickListener(new OnItemClickListener(position));
return v;
}
public void onClick(int position, View view) {
// this log always reports the correct position when i select a list item
Log.i(new Integer(position).toString(), books.get(position).title);
if(selected != null) {
selected.setBackgroundResource(R.drawable.list_view_bg);
}
selected = view;
selected.setBackgroundResource(R.color.listSelected);
}
private class OnItemClickListener implements OnClickListener{
private int mPosition;
OnItemClickListener(int position){
mPosition = position;
}
@Override
public void onClick(View view) {
BookListAdapter.this.onClick(mPosition, view);
}
}
}
Ответ №1:
ListView перерабатывает представления (часть с View v = convertView; if (v == null) { } ...
), поэтому вы устанавливаете фон для представления, которое будет использоваться снова и снова. Вместо этого вам также необходимо установить флаг «selected» для вашей модели (самого Book
объекта). В той части вашего getView
, которая закомментирована, вы затем говорите:
if (book.isSelected()) {
v.setBackgroundResource(R.color.listSelected)
}
Комментарии:
1. Итак, я прав, полагая, что при прокрутке списка вниз он вызывает метод getView для создания других элементов в списке по мере их приближения к просмотру?
2. Да,
getView()
вызывается для каждой строки. Он сохраняет более или менее количество видимых представлений в кэше и повторно использует их после этого. Таким образом, при прокрутке вниз тот же вид, который использовался для первого элемента, будет использоваться для элемента n 1 (или около того). Вот почему вы должны каждый раз устанавливать каждое свойство, которое вам нужно, в представлении, включая фон.