Просмотр списка Прокрутите до конца списка после обновления списка


292

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

Я попробовал это, но не повезло:

lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

Спасибо


попробуйте сделать это, это работает ... messagesListView.setTranscriptMode (ListView.TRANSCRIPT_MODE_NORMAL); messagesListView.setStackFromBottom (истина);
Супердев,

lv.setTranscriptMode (ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL) только гарантирует, что listView будет прокручиваться вниз после вызова adapter.notifyDataSetChanged. Если это не работает, попробуйте определить это свойство в XML, как вы можете увидеть в постах ниже.
Том

Ответы:


418

Предположим, вы знаете, когда изменились данные списка, вы можете вручную указать, что список прокручивается вниз, установив выбор списка в последнюю строку. Что-то вроде:

private void scrollMyListViewToBottom() {
    myListView.post(new Runnable() {
        @Override
        public void run() {
            // Select the last row so it will scroll into view...
            myListView.setSelection(myListAdapter.getCount() - 1);
        }
    });
}

@ Бхупендра, это не обязательно. Вы также можете обойтись без нити, как показано в ответе Warting.
sagarpatidar

2
@Bhupendra setSelection () обновляет интерфейс. Вызывая post (Runnable) в представлении, вы гарантируете, что Runnable код запускается в потоке пользовательского интерфейса Android. Как правило, делайте это таким образом, если вы не знаете, что уже находитесь в потоке пользовательского интерфейса или не гарантируете это другими способами.
Мейсон Ли

5
также кажется, что использование post на вновь установленном адаптере вызывает анимацию прокрутки, при этом гарантируя, что он находится в главном потоке, а использование setSelection сразу после установки адаптера не вызывает анимацию прокрутки
Джанлука П.

1
@SaifHamed, как прокомментировал Мейсон Ли в ответе Кевина, это также приводит к тому, что короткие списки имеют «пустое» пространство вверху представления вместо нижнего, что, скорее всего, не соответствует предполагаемому поведению.
марионетка

16
Вы также можете использовать myListView.smoothScrollToPosition (myListAdapter.getCount () - 1); для плавной прокрутки
Zar E Ahmer

238

Вам нужно использовать эти параметры в вашем списке:

  • манускрипт lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

  • Установите заголовок списка внизу lv.setStackFromBottom(true);

Вы также можете установить эти параметры в XML, например. как это:

<ListView
   ...
   android:transcriptMode="alwaysScroll"
   android:stackFromBottom="true" />

27
Обратите внимание, что при таком подходе строки «складываются снизу» представления по мере их добавления. Это означает, что короткие списки будут иметь «пустое» пространство вверху представления, а не внизу, что не всегда то, что нужно.
Мейсон Ли

2
Быстрый вопрос: каким-нибудь образом я могу получить прокрутку для анимации? Потому что в настоящее время, когда я notifyDataSetChanged () он прыгает без анимации?!?
Георг

@ Georg Вы отключили анимацию в настройках разработчика на вашем устройстве, возможно?
JonasCz - Восстановить Монику

35

Комбинация TRANSCRIPT_MODE_ALWAYS_SCROLL и setSelection заставила меня работать

ChatAdapter adapter = new ChatAdapter(this);

ListView lv = (ListView) findViewById(R.id.chatList);
lv.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
lv.setAdapter(adapter);

adapter.registerDataSetObserver(new DataSetObserver() {
    @Override
    public void onChanged() {
        super.onChanged();
        lv.setSelection(adapter.getCount() - 1);    
    }
});

29

Я успешно использовал это в ответ на нажатие кнопки, поэтому я думаю, что вы можете использовать его и после обновления содержимого:

myListView.smoothScrollToPosition(theListAdapter.getCount() -1);

1
Это отличное решение. Простая, одна строка.
Джош Ларсон

12

Чтобы получить это в ListFragment:

getListView().setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL); 
getListView().setStackFromBottom(true);`

Добавил этот ответ, потому что если кто-то делает поиск в Google для той же проблемы с ListFragment, он просто находит это ..

С уважением


9

Использование: установить заголовок списка внизу lv.setStackFromBottom(true);

Сработало для меня, и список автоматически прокручивается до самого дна, когда он впервые отображается. Затем список прокручивается как следует TRANSCRIPT_MODE_ALWAYS_SCROLL.


6
Обратите внимание, что при таком подходе строки «складываются снизу» представления по мере их добавления. Это означает, что короткие списки будут иметь «пустое» пространство вверху представления вместо нижнего.
Мейсон Ли

5

я использую

setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);

добавить записи внизу, а старые записи прокрутить сверху, как стенограмма чата


Позвоните getListView().smoothScrollToPosition(getListAdapter.getCount() - 1);в onstart, чтобы перейти к нижней части в начале упражнения.
Палиндром

4

Самое простое решение:

    listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
    listView.setStackFromBottom(true);

3

Режим расшифровки - это то, что вы хотите, и он используется Google Talk и приложением SMS / MMS. Правильно ли вы вызываете notifyDatasetChanged () на вашем адаптере при добавлении элементов?


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

Режим расшифровки фактически отключен приложением SMS. Я не могу вспомнить почему именно.
Тимммм
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.