9

I set a timer in my app, I could get some information from a web service and resulted in a list view to display. Now my problem is that every time the timer runs, scroll back to the beginning ...

how can i keep Scroll position with every refresh in list view ?

part of my code:

runOnUiThread(new Runnable() {
    public void run() {
        /**
         * Updating parsed JSON data into ListView
        * */
        ListAdapter adapter = new SimpleAdapter(DashboardActivity.this, 
                                                all_chat, 
                                                R.layout.list_item, 
                                                new String[] { TAG_FULLNAME,
                                                               TAG_DATE, 
                                                               TAG_MESSAGE }, 
                                                new int[] { R.id.fullname,
                                                            R.id.date, 
                                                            R.id.message }
                                               );
        // updating listview
        setListAdapter(adapter);
    }
});

TNx.

Melquiades
  • 8,496
  • 1
  • 31
  • 46
l3l4c7_h4t
  • 129
  • 1
  • 1
  • 5
  • http://stackoverflow.com/a/3035521/931982 – stinepike Apr 18 '13 at 20:41
  • possible duplicate of [Maintain/Save/Restore scroll position when returning to a ListView](http://stackoverflow.com/questions/3014089/maintain-save-restore-scroll-position-when-returning-to-a-listview) – stinepike Apr 18 '13 at 20:41
  • These links do not solve my problem, Because my problem is another thing. my listview Automatically receives a data from Web service and then Scroll position back to the beginning (top position)...., I hope u undrestan me ... tnx. – l3l4c7_h4t Apr 18 '13 at 21:38
  • 6
    cmon people, he sets every time new adapter, he should update it instead or use function like addElement and then calling notifyDataSetChange.. After second look at your problem you should do something like this: call clear, call add element in loop, call notifydatasetchange. Clearing depends if your elements are always new or just the same with some new – deadfish Oct 04 '13 at 09:08
  • Setting adapter every time seems evil but still people keep doing it... – M-Wajeeh Oct 09 '13 at 18:44

4 Answers4

14

Do not call setAdapter(). Do something like this:

ListAdapter adapter; // declare as class level variable

runOnUiThread(new Runnable() {
    public void run() {
        /**
         * Updating parsed JSON data into ListView
         */
        if (adapter == null) {
            adapter = new SimpleAdapter(
                    DashboardActivity.this, all_chat, R.layout.list_item, new String[]{TAG_FULLNAME, TAG_DATE, TAG_MESSAGE},
                    new int[]{R.id.fullname, R.id.date, R.id.message});
            setListAdapter(adapter);
        } else {
            //update only dataset   
            allChat = latestetParedJson;
            ((SimpleAdapter) adapter).notifyDataSetChanged();
        }
        // updating listview
    }
});
Makoto
  • 104,088
  • 27
  • 192
  • 230
Biraj Zalavadia
  • 28,348
  • 10
  • 61
  • 77
  • 3
    Are `allChat` and `all_chat` same variables? Passing allChat to adapter constructor and then changing allChat reference does not mean that allChat will be changed in adapter. – mixel Oct 17 '13 at 07:57
6

You can add the following attribute to your ListView in xml.

android:stackFromBottom="true"
android:transcriptMode="alwaysScroll" 

Add these attributes and your ListView will always be drawn at bottom like you want it to be in a chat.

or if you want to keep it at the same place it was before, replace alwaysScroll to normal

in the android:transcriptMode attribute. 

Cheers!!!

Menma
  • 799
  • 1
  • 9
  • 35
Hitesh
  • 331
  • 2
  • 10
2

I had the same issue, tried a lot of things to prevent the list from changing its scroll position, including:

android:stackFromBottom="true"
android:transcriptMode="alwaysScroll"

and not calling listView.setAdapter(); None of it worked until I found this answer:

Which looks like this:

// save index and top position
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - mList.getPaddingTop());

// ...

// restore index and position
mList.setSelectionFromTop(index, top);

Explanation:

ListView.getFirstVisiblePosition() returns the top visible list item. But this item may be partially scrolled out of view, and if you want to restore the exact scroll position of the list you need to get this offset. So ListView.getChildAt(0) returns the View for the top list item, and then View.getTop() - mList.getPaddingTop() returns its relative offset from the top of the ListView. Then, to restore the ListView's scroll position, we call ListView.setSelectionFromTop() with the index of the item we want and an offset to position its top edge from the top of the ListView.

Community
  • 1
  • 1
Luis Rita
  • 372
  • 3
  • 6
1

There's a good article by Chris Banes. For the first part, just use ListView#setSelectionFromTop(int) to keep the ListView at the same visible position. To keep the ListView from flickering, the solution is to simply block the ListView from laying out it's children.

f2prateek
  • 2,034
  • 2
  • 20
  • 26