1

我有一个由 ResourceCursorAdapter 填充的 ListView。我使用加载器机制来查询 ContentProvider 的列表项。我检测到列表项上的滑动手势以对它们执行一些操作。新项目由后台服务添加,因此列表可以动态更改。

一切正常,除非我开始刷卡并发生数据库更改(由于后台服务添加了新行)。在这种情况下,无法正确检测到手势。我注意到 ACTION_CANCEL 被分派到列表项视图,并且对所有可见项执行了 bindView。在 bindView 方法中,我只设置了一些文本 - 我没有更改任何侦听器。

即使后台服务正在添加新项目,如何使手势起作用?也许有一种方法可以防止动作被取消,或者我可以暂停数据库更新,这样它们就不会中断手势。

4

3 回答 3

0

在您的 ResourceCursorAdapter 中为您的视图设置一个触摸侦听器newView()。您可能需要修改适配器的构造函数以传递触摸侦听器以在newView().

于 2013-07-03T11:10:34.097 回答
0

您需要将更新与数据和 UI 分离。这会有点难看。

1)不要使用光标适配器。将游标的结果加载到某个数据结构中,并让适配器使用该数据副本。然后,当您获得新数据时,创建该数据结构的新副本,然后将其保存到适配器查看的变量中并调用 notifyDataSetChanged。这样更改光标和更新屏幕就没有关联。

2)服务更新游标时,不自动更新listview。然后继承 ListView。当您从服务获取更新时,请保存新数据但不要更新列表视图。相反,设置一个标志。在新的 ListView 子类中,重写 onTouchEvent 以便在发生 ACTION_UP 事件时,您还可以检查该标志。如果设置了标志,则将其设置为 false,然后在适配器上通知 DataSetChanged。这样,列表在用户完成滚动之前不会更新。

于 2013-07-03T11:16:44.800 回答
0

我最终用以下方法解决了这个问题。

在我的列表适配器中,我有一个标志:

private boolean mIsSwiping;

当用户开始滑动时,我将其设置为 true,当任何滑动操作完成时(可能通过自动动画),我将其设置为 false。

在 getView() 的顶部,我检查标志的值,并在需要时提前返回。这可以防止重新绘制错误的列表视图项。

if (convertView != null && mIsSwiping) {
    return convertView;
}

此外,在使用适配器的片段中,我有类似的逻辑,但将其应用于游标加载逻辑:

private Cursor mNewCursor;

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    if (mListAdapter.isSwiping()) {
        mNewCursor = cursor;

    } else {
        mListAdapter.swapCursor(cursor);
        mNewCursor = null;

    }
}

然后在同一个片段中,就在将 mListFragment 的 mIsSwiping 标志设置为 false 之前:

if (mNewCursor != null) {
    mListFragment.swapCursor(mNewCursor);
    mNewCursor = null;
}

希望这会有所帮助——它实际上只是用一些具体的代码充实了上面的 Gabe 的答案。

您可能需要单独跟踪的一件事是 mNewCursor 在换出之前是否已关闭。我自己没有遇到过这个问题,但是 YMMV。

于 2013-10-30T21:55:17.437 回答