在Android ListView项目上滑动手势

时间:2013-07-03 11:03:22

标签: java android android-listview android-cursoradapter android-loader

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

一切正常,除非我开始滑动并发生数据库更改(后台服务添加新行的结果)。在这种情况下,未正确检测到手势。我注意到ACTION_CANCEL被调度到列表项视图,并且还对所有可见项执行bindView。在bindView方法中我只设置了一些文本 - 我不会在那里更改任何监听器。

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

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分: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。

相关问题