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

292

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

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

lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

Спасибо

jramirez
источник
попробуйте сделать это, это работает ... 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" />
dev.serghini
источник
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);    
    }
});
Wärting
источник
29

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

myListView.smoothScrollToPosition(theListAdapter.getCount() -1);
Álex
источник
1
Это отличное решение. Простая, одна строка.
Джош Ларсон
12

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

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

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

С уважением

Klatschen
источник
9

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

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

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

я использую

setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);

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

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

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

    listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
    listView.setStackFromBottom(true);
ucMedia
источник
3

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

Ромэн Гай
источник
Да, я. список корректно обновляется, но всегда начинается сверху. Мне просто нужно, чтобы добавить новый элемент и всегда прокручивать до конца списка.
Джрамирез
Режим расшифровки фактически отключен приложением SMS. Я не могу вспомнить почему именно.
Тимммм