Хаки onTouchEvent () и layoutChildren () больше не нужны после внесения этого изменения.

е: Попытка динамически добавить строки заголовка в ListView через пользовательскую оболочку адаптера. У ListView возникают проблемы с синхронизацией позиции прокрутки. Запуск демо-проекта.

Я хотел бы динамически добавлять элементы в список на основе значений в CursorAdapter, на несколько позиций впереди того, что в данный момент просматривает пользователь. Для этого у меня есть адаптер, который оборачивает CursorAdapter и сохраняет индексированное новое содержимое в SparseArray. ListView необходимо обновить, когда элементы добавляются в пользовательский адаптер, но я столкнулся с множеством ловушек, пытаясь заставить это работать, и хотел бы получить несколько советов.

Демо-проект можно скачать здесь:DynamicSectionedList.zip

В демонстрации заголовки добавляются динамически, если смотреть на 10 мест вперед, чтобы найти правильную позицию, в которой элементы списка переключаются на следующую букву. Каждая реализация notifyDataSetChanged имеет проблемы, как описано:

Демо 1 Эта демонстрация показывает важность notifyDataSetChanged (). При нажатии на что-либо, приложение будет зависать. Это связано с проверкой работоспособности в ListView ...mItemCount != adapter.getItemCount(), Мораль в том, что нам нужно уведомить список, что данные изменились.

Демо 2 Следующим естественным шагом является уведомление ListView об изменениях, когда они происходят. К сожалению, выполнение во время прокрутки ListView полностью прерывает взаимодействие сенсорного экрана до тех пор, пока приложение не выйдет из сенсорного режима. Вам нужно будет "пролистать свиток" достаточно далеко, чтобы генерировать новые заголовки, чтобы заметить это. Прикосновение к экрану не приведет к остановке прокрутки, и после остановки ни один из элементов списка не будет активным. Это связано с некоторымиif (!mDataChanged) { /* do very important stuff */ } код в AbsListView.onTouchEvent ().

Демо 3 Чтобы исправить это, в демонстрационной версии 3 представлен флаг pendingChanges, и пользовательский адаптер получает notifyDataSetChangedIfNeeded (), который может вызываться ListView после перехода в «безопасное» состояние для изменений. Первая точка, где изменения должны быть уведомлены, находится в ListView.layoutChildren (), поэтому я переопределил этот метод, чтобы сначала уведомить об изменениях при необходимости, а затем вызвать через. Пролистав хотя бы один заголовок, щелкните элемент списка.

Это не совсем правильно, хотя я не совсем уверен, почему. При нажатии или выборе элемента с помощью клавиатуры / трекбола список обновляется без правильной синхронизации старой позиции. Он прокручивается до верхней части списка, что недопустимо.

Демо 4 Проблему прокрутки в Demo 3 можно преодолеть, по крайней мере, в сенсорном режиме. Добавляя вызов метода notifyDataSetChangedIfNeeded () при касании, происходит изменение данных в такое время, когда все взаимодействия касанием работают должным образом и позиция списка синхронизируется должным образом.

Тем не менее, я не могу найти аналог для этого, когда устройство не находится в сенсорном режиме, не говоря уже о том, что это определенно похоже на взлом. Список почти всегда прокручивается до самого верха, я не могу выяснить, из-за чего он иногда сохраняет правильную позицию.

Поскольку Android борется со мной на каждом этапе пути, я чувствую, что должен быть лучший подход. Пожалуйста, попробуйте демо, если какие-то исправления могут быть применены, чтобы это работало, это было бы здорово!

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

Ответы на вопрос(0)

Ваш ответ на вопрос