在Android中更改光标后,在List Fragment中保留位置

时间:2014-09-07 00:29:42

标签: android

我通过使用列表片段扩展AsyncTaskLoader来使用SQLiteCursorLoader,我设法通过保存位置和视图来保留新数据的位置,然后使用setSelectionFromTop(),这非常正常。

这就是它目前的工作方式,

光标重载前的数据库,

Field1 int, timestamp long
------------------
First row, now  
Second row, 1 minute ago
Third row, 2 minutes ago  -----> user is currently on this item in the listview

光标重载后的数据库

Field1 int, timestamp long
------------------
Fourth row, now
First row, 30 secon ago
Second row, 1 minute + 30 seconds ago
Third row, 2 minutes + 30 seconds ago --> go here using setSelectionFromTop(position, y)

光标重新加载后,我保留"第三行"的位置。因为我保存旧位置, 所以我需要做的就是计算旧位置 - 新光标数

现在我有一个新的要求(如下所示),不仅会有新数据进入,而且旧数据也会发生变化,这会使位置变得混乱,旧数据的时间戳会发生什么变化,所以结果SQLiteCursorLoader中使用的查询会有所不同,我不能再使用旧方法了。

Field1 int, timestamp long
------------------
First row, now  
Second row, 1 minute ago
Third row, 2 minutes ago  -----> user is currently on this item in the listview

光标重载后的数据库

Field1 int, timestamp long
------------------
Third row, now
First row, 30 secon ago
Second row, 1 minute + 30 seconds ago

正如您所看到的,现在的位置不会相同。现在我必须使用getItemId获取DB id并保存它,当光标重新加载时,我将不得不通过它来获得它的位置。

我的问题是,是否有可能以另一种/更快的方式做到这一点?

如果您需要更多说明,请与我们联系。

1 个答案:

答案 0 :(得分:0)

这个解决方案有选择地阻止ListView布局它的孩子。为什么它不保留它的位置是ListView布置它的孩子在旧位置显示新项目。如果我们停止子布局通过,我们就会停止可见的位置变化。

制作一个像这样的cutom Listview小部件:

public class BlockingListView extends ListView {

    private boolean mBlockLayoutChildren;

    public BlockingListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setBlockLayoutChildren(boolean block) {
        mBlockLayoutChildren = block;
    }

    @Override
    protected void layoutChildren() {
        if (!mBlockLayoutChildren) {
            super.layoutChildren();
        }
    }
}

并像这样使用这个新的小部件..

int firstVisPos = mListView.getFirstVisiblePosition();
View firstVisView = mListView.getChildAt(0);
int top = firstVisView != null ? firstVisView.getTop() : 0;

// Block children layout for now 
mListView.setBlockLayoutChildren(true);

// Number of items added before the first visible item 
int itemsAddedBeforeFirstVisible = ...;

// Change the cursor, or call notifyDataSetChanged() if not using a Cursor
mAdapter.swapCursor(...);

// Let ListView start laying out children again 
mListView.setBlockLayoutChildren(false);

// Call setSelectionFromTop to change the ListView position
mListView.setSelectionFromTop(firstVisPos + itemsAddedBeforeFirstVisible, top);