每次刷新列表视图时保持滚动位置

9
我在我的应用程序中设置了一个定时器,可以从Web服务获取一些信息,并将其结果显示在列表视图中。现在我的问题是,每次定时器运行时,都会滚动回到开头...
如何在列表视图中保留每次刷新的滚动位置?
我的代码部分:
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. (感谢您)

https://dev59.com/dXA75IYBdhLWcg3w8-HZ#3035521 - stinepike
这些链接并不能解决我的问题,因为我的问题是另一件事。我的ListView自动从Web服务接收数据,然后滚动位置回到开头(顶部位置)......,我希望你能理解我...谢谢。 - l3l4c7_h4t
6
大家加油,他每次都设置新的适配器,应该更新它或使用诸如addElement之类的函数,然后调用notifyDataSetChange等功能。在仔细查看您的问题后,您应该这样做:调用clear,循环调用addElement,调用notifyDataSetChanged。清除取决于您的元素是否始终是新的,还是只是与一些新元素相同。 - deadfish
每次设置适配器似乎都很麻烦,但人们仍然坚持这样做... - M-Wajeeh
4个回答

14

不要调用setAdapter()。做类似于这样的事情:

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
    }
});

3
allChatall_chat是相同的变量吗?将allChat传递给适配器构造函数并更改allChat引用并不意味着适配器中的allChat会被更改。 - mixel

6
您可以在xml中向您的ListView添加以下属性。
android:stackFromBottom="true"
android:transcriptMode="alwaysScroll" 

添加这些属性后,您的ListView将始终像聊天中所需的那样在底部绘制。
或者,如果您想保持它在之前的位置,请将alwaysScroll替换为normal
in the android:transcriptMode attribute. 

干杯!!!

2

我遇到了同样的问题,尝试了许多方法来防止列表改变其滚动位置,包括:

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

在没有调用 listView.setAdapter(); 的情况下,所有尝试都失败了,直到我找到了这个答案

它看起来像这样:

// 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);

解释:

ListView.getFirstVisiblePosition() 返回顶部可见列表项。但是该项可能只有部分滚动出视图,如果您想恢复列表的精确滚动位置,则需要获取此偏移量。因此,ListView.getChildAt(0) 返回顶部列表项的View,然后View.getTop() - mList.getPaddingTop() 返回其相对于ListView顶部的偏移量。然后,为了恢复ListView的滚动位置,我们使用所需项的索引和从ListView顶部定位其顶部边缘的偏移量调用ListView.setSelectionFromTop()


1

这里有一篇Chris Banes写的好文章。对于第一部分,只需使用ListView#setSelectionFromTop(int)来保持ListView在相同的可见位置。为了防止ListView闪烁,解决方案就是简单地阻止ListView布局其子项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接