HorizontalScrollView: CustomAdapter с getView () не повторно использует convertView, такие как ListView

В одном из моих прошлых проектов я реализовал «Карусель времени». Он основан на HorizontalScrollView . Пользователь может выбрать время, прокручивая это представление. Значение времени рассчитывается из X-смещения HorizontalScrollView .

Введите описание изображения здесь

Я хотел поделиться этим проектом в github, но, читая код, я понял, что проблема была плохой .

HorizontalScrollView заполняется настраиваемым ArrayAdapter . getView() использует Holder для convertView . Я думал, что это может работать как адаптер в ListView , поэтому только видимые элементы визуализируются и повторно используются, если они будут уничтожены. Вместо этого все предметы визуализируются !!! (В моем случае 1008!) Я добавляю их сам (# 1 в примере кода), но даже если я пытаюсь добавить меньше, логика от удаления (и переработка) старых не работает или мне что-то не хватает?

Поэтому мой основной вопрос: что мне нужно изменить, чтобы сделать мой адаптер таким же, как ListView ?

  1. Я нашел эту ссылку и попытался переопределить функцию remove , но это никогда не называется (как-то логично, потому что я только добавляю)
  2. В github есть хороший пример PagerAdapter , но почему-то я не могу перевести его в ArrayAdapter<String>

Любые мысли, ссылки приветствуются!

И, пожалуйста, не предлагайте вместо этого использовать ListView . Мы решили использовать HorizontalScrollView из-за обратных вызовов и тот факт, что у нас уже есть ListView в макете.

HorizontalScrollView

 InfiniteTimeScrubberHorizontalView extends HorizontalScrollView{ ... public void setAdapter(Context context, TimeScrubberListAdapter mAdapter) { this.mAdapter = mAdapter; try { fillViewWithAdapter(mAdapter); } catch (ZeroChildException e) { e.printStackTrace(); } } private void fillViewWithAdapter(TimeScrubberListAdapter mAdapter) { //... ViewGroup parent = (ViewGroup) getChildAt(0); parent.removeAllViews(); for (int i = 0; i < mAdapter.getCount(); i++) { //#1: Here: ALL views are added parent.addView(mAdapter.getView(i, null, parent)); } } 

Adpater

 public class TimeScrubberListAdapter extends ArrayAdapter<String> { //... private ArrayList<String> list; //list from 0:00,0:30...23:00,23:30 final static int MAXIMUM_DAYS = 21 @Override public int getCount() { return list.size() * MAXIMUM_DAYS; } @Override public String getItem(int position) { return list.get(position % list.size()); } @Override public View getView(final int position, View convertView, ViewGroup parent) { RelativeLayout layout; if (convertView == null) { layout = (RelativeLayout) View.inflate(context, layoutId, null); holder = new Holder(); holder.title = (TextView) layout.findViewById(R.id.epg_item_text); layout.setTag(holder); } else { layout = (RelativeLayout) convertView; view = layout; holder = (Holder) layout.getTag(); } layout.setLayoutParams(mLP); String timeValue = getItem(position); holder.title.setText(timeValue); return layout; } //... @Override public void remove(String object) { //not called...some how logic, because i do not remove an item super.remove(object); } 

Я думаю, может быть, вы запутались, где логика заключается в рендеринге между View и Adapter. Использование адаптера не приводит к изменению режима просмотра. Это сам ListView вместе со своим родителем AbsListView , который реализует поведение рециркуляции представления. Адаптер требуется ListView для правильного заполнения Представлений, отображаемых на экране по мере необходимости, но логика для фактического выбора того, какие представления отображать, а также когда и как перерабатывать эти представления вообще не входит в адаптер.

Если вы посмотрите на исходный код для HorizontalScrollView и ListView , вы увидите, что они сильно отличаются друг от друга. Это не одно и то же в разных ориентациях.

Таким образом, длинный и короткий, так это то, что вы не сможете получить переработанную рекламу, которую ищете, используя HorizontalScrollView или даже простой потомок. Если вы хотите просмотреть переработку, вы должны проверить RecyclerView .

ScrollView сохраняет все дочерние представления в памяти, поэтому проблема с производительностью является общей при использовании.

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

  • Android-HorizontalListView

  • HorizontalVariableListView

Эти библиотеки представляют собой горизонтальную реализацию ListView, которая выполняет переработку элементов для вас, на основе которых видны на экране. Scrollview – плохой выбор для просмотра inifinite прокрутки.

UPDATE : теперь у нас есть RecyclerView от самого Android, который также поддерживает горизонтальную прокрутку, а также обеспечивает использование шаблона Viewholder