299

I would like to make sure that the list is scrolled all the way to the bottom, after I have updated the listview by using listAdapter, so that it displays the last element entered in the list. How can I do this ?

I tried this but no luck:

lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

thank you

jramirez
  • 8,537
  • 7
  • 33
  • 46
  • try doing this it works...messagesListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL); messagesListView.setStackFromBottom(true); – Superdev Apr 22 '14 at 08:07
  • lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL) only ensures that listView will be scrolled down after calling adapter.notifyDataSetChanged. If this is not working, try to define this property in xml as you can see in posts below. – tomm May 09 '15 at 19:13

9 Answers9

428

Supposing you know when the list data has changed, you can manually tell the list to scroll to the bottom by setting the list selection to the last row. Something like:

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);
        }
    });
}
sulai
  • 5,204
  • 2
  • 29
  • 44
Mason Lee
  • 5,130
  • 1
  • 20
  • 15
  • @Bhupendra that is not necessary. You can do without thread too, as shown in Warting's answer. – sagarpatidar Feb 16 '14 at 00:46
  • 2
    @Bhupendra setSelection() updates the UI. By calling post(Runnable) on the view, you ensure the Runnable code is run on the android UI thread. Generally do it this way unless you know you're already on the UI thread, or are ensuring that by some other means. – Mason Lee Feb 19 '14 at 00:14
  • 5
    it also seems that using post on a newly set adapter causes scroll animation while ensuring to be in main thread and using setSelection immediately after setting the adapter causes no scroll animation – Gianluca P. Jun 04 '14 at 15:42
  • This answer is not good enough if the last item is too large, it will scroll to the head of the last item. Use `setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL)` and `setStackFromBottom(true)` for better result. – Saif Hamed Nov 25 '14 at 11:46
  • 1
    @SaifHamed as commented by Mason Lee on the answer of Kevin, this also causes short lists to have "empty" space at the top of the view instead of the bottom which is most likely not the intended behaviour. – dashhund Mar 17 '15 at 14:57
  • 16
    you can also use myListView.smoothScrollToPosition(myListAdapter.getCount()-1); for smooth scrolling – Zar E Ahmer May 13 '15 at 07:08
  • @MasonLee can you please tell me how can 1 fix the problem described by Saif Hamed without having to `setStackFromBottom(true)`? – Akash Agarwal Apr 03 '16 at 10:02
241

You need to use these parameters in your list view:

  • Scroll lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

  • Set the head of the list to it bottom lv.setStackFromBottom(true);

You can also set these parameters in XML, eg. like this:

<ListView
   ...
   android:transcriptMode="alwaysScroll"
   android:stackFromBottom="true" />
Jonas Czech
  • 12,018
  • 6
  • 44
  • 65
dev.serghini
  • 2,989
  • 1
  • 17
  • 8
  • 29
    Note that with this approach, rows "stack from the bottom" of the view as they are added. This means that short lists will have "empty" space at the top of the view instead of the bottom, which is not always what one wants. – Mason Lee Aug 11 '11 at 20:36
  • 2
    Quick question: Any way I can get the scrolling to be animated? Cause currently when I notifyDataSetChanged() it jumps with no animation?!? – Georg Jan 19 '15 at 15:57
  • @Georg Have you disabled animations in Developer Options on your device perhaps ? – Jonas Czech May 13 '15 at 11:43
37

A combination of TRANSCRIPT_MODE_ALWAYS_SCROLL and setSelection made it work for me

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
  • 1,086
  • 1
  • 12
  • 19
31

I've had success using this in response to a button click, so I guess that you can use it too after updating your contents:

myListView.smoothScrollToPosition(theListAdapter.getCount() -1);
Mason Lee
  • 5,130
  • 1
  • 20
  • 15
Álex
  • 1,587
  • 11
  • 17
11

To get this in a ListFragment:

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

Added this answer because if someone do a google search for same problem with ListFragment he just finds this..

Regards

Klatschen
  • 1,652
  • 19
  • 32
9

Using : Set the head of the list to it bottom lv.setStackFromBottom(true);

Worked for me and the list is scrolled to the bottom automatically when it is first brought into visibility. The list then scrolls as it should with TRANSCRIPT_MODE_ALWAYS_SCROLL.

Pratik Butani
  • 60,504
  • 58
  • 273
  • 437
Kevin Parker
  • 16,975
  • 20
  • 76
  • 105
  • 8
    Note that with this approach, rows "stack from the bottom" of the view as they are added. This means that short lists will have "empty" space at the top of the view instead of the bottom. – Mason Lee Aug 11 '11 at 20:34
5

I use

setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);

to add entries at the bottom, and older entries scroll off the top, like a chat transcript

Plugie
  • 1,289
  • 17
  • 25
  • Call `getListView().smoothScrollToPosition(getListAdapter.getCount() - 1);` in onstart to scroll to the bottom in the begining of the activity. – palindrom Jan 29 '15 at 14:59
3

The transcript mode is what you want and is used by Google Talk and the SMS/MMS application. Are you correctly calling notifyDatasetChanged() on your adapter when you add items?

Romain Guy
  • 97,993
  • 18
  • 219
  • 200
  • yes I am. the list correctly gets updated, but always start from the top. I just need it to add the new item and always scroll to the end of the list. – jramirez Aug 31 '10 at 15:49
  • Transcript mode is actually disabled by the SMS app. I can't remember why exactly. – Timmmm Nov 05 '12 at 12:06
3

The simplest solution is :

    listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
    listView.setStackFromBottom(true);
ucMedia
  • 4,105
  • 4
  • 38
  • 46