Просмотр списка привязки к элементу

Я создаю список изображений, используя ListView, и фотографии имеют размер, который будет содержать от 2 до 3 фотографий на экране.

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

Есть ли способ достичь этого в android со списком?

Я нашел способ сделать это, просто прослушивая прокрутку и изменяя позицию, когда прокрутка закончилась, реализовав ListView.OnScrollListener

@Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { case OnScrollListener.SCROLL_STATE_IDLE: if (scrolling){ // get first visible item View itemView = view.getChildAt(0); int top = Math.abs(itemView.getTop()); // top is a negative value int bottom = Math.abs(itemView.getBottom()); if (top >= bottom){ ((ListView)view).setSelectionFromTop(view.getFirstVisiblePosition()+1, 0); } else { ((ListView)view).setSelectionFromTop(view.getFirstVisiblePosition(), 0); } } scrolling = false; break; case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: case OnScrollListener.SCROLL_STATE_FLING: Log.i("TEST", "SCROLLING"); scrolling = true; break; } } 

Изменение не так гладко, но оно работает.

Используя пару идей из решения @ nininho, я получил свой список для привязки к элементу с гладким свитком вместо того, чтобы резко перейти к нему. Одно из предостережений в том, что я тестировал это решение только на Moto X в базовом ListView с текстом, но он отлично работает на устройстве. Тем не менее, я уверен в этом решении и предлагаю вам обратную связь.

 listview.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // TODO Auto-generated method stub if (scrollState == SCROLL_STATE_IDLE) { View itemView = view.getChildAt(0); int top = Math.abs(itemView.getTop()); int bottom = Math.abs(itemView.getBottom()); int scrollBy = top >= bottom ? bottom : -top; if (scrollBy == 0) { return; } smoothScrollDeferred(scrollBy, (ListView)view); } } private void smoothScrollDeferred(final int scrollByF, final ListView viewF) { final Handler h = new Handler(); h.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub viewF.smoothScrollBy(scrollByF, 200); } }); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // TODO Auto-generated method stub } }); 

Причина, по которой я откладываю гладкую прокрутку, заключается в том, что при моем тестировании прямое обращение к методу smoothScrollBy в состоянии измененного обратного вызова имело проблемы с прокруткой. Кроме того, я не предвижу полностью протестированное, надежное решение, поддерживающее очень много состояний, и в моем решении ниже я не имею никакого состояния. Это решение еще не включено в Google Play Store, но оно должно служить хорошей отправной точкой.

Используя решение @nininho,

В onScrollStateChanged когда состояние изменяется на SCROLL_STATE_IDLE , запомните позицию, чтобы привязать и поднять флаг:

 snapTo = view.getFirstVisiblePosition(); shouldSnap = true; 

Затем переопределите метод computeScroll() :

 @Override public void computeScroll() { super.computeScroll(); if(shouldSnap){ this.smoothScrollToPositionFromTop(snapTo, 0); shouldSnap = false; } } 

Вы можете сделать гораздо более гладкую прокрутку, если используете RecyclerView. OnScrollListener лучше.

Я привел пример здесь: https://github.com/plattysoft/SnappingList

Помимо проверки кода выше, вы должны убедиться в том, что ваш listView имеет высоту, которая может соответствовать точному количеству элементов, которые вы хотите отобразить. Например, если вы хотите отобразить 4 элемента после эффекта привязки, а высота строки (определенная в ее макете) должна быть 1/4 от общей высоты списка.

Обратите внимание, что после smoothScrollBy() getFirstVisiblePosition() может указывать на элемент списка ВЫШЕ верхний в списке. Это особенно актуально, когда view.getChildAt(0).getBottom() == 0 . Мне пришлось вызвать view.setSelection(view.getFirstVisiblePosition() + 1) чтобы исправить это странное поведение.

  • Еще один getView вызвал несколько раз
  • Как загрузить Listview «плавно» в android
  • ListView пуст при использовании функции getFilter
  • Android: как установить событие onClick для кнопки в элементе списка в ListView
  • Android: wrap_content не работает с ListView
  • OnItemCLickListener не работает в listview
  • ListView OnItemClickListener не отвечает?
  • Просмотр списка Android-файлов Drag and Drop
  • setOnItemClickListener в пользовательском ListView
  • как настроить listview row android
  • Почему ListView.getCheckedItemPositions () не возвращает правильные значения?
  • Давайте будем гением компьютера.