停止ListView滚动动画。

3

我有一个包含大约100个条目的ListView。当用户从底部向上进行“fling”操作时,它开始滚动,并且即使手指不再触摸显示屏,它仍然会继续滚动。

有没有办法在这一点上停止滚动动画?

6个回答

16

我们查找了Android源代码(AbsListView),给它一个ACTION_CANCEL的touchEvent,就可以停止fling。这很容易。

listView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0));

1
这是正确的答案。它可以在不需要反射的情况下工作,因此应该被接受。干得好伙计! - A. Steenbergen

9
我没有尝试过Pompe de velo的解决方案,但由于低于API 8的版本中没有smoothScrollToPosition(),所以这对我没有用。

我同意,改变默认行为不是一个好主意,但有时你需要这样做。因此,这是我的(肮脏)解决方案,它使用了反射。这绝不是推荐的方式,因为它是一种hack,但它对我有效。可能会有更好的解决方案,但我没有找到。

class StopListFling {

    private static Field mFlingEndField = null;
    private static Method mFlingEndMethod = null;

    static {
        try {
            mFlingEndField = AbsListView.class.getDeclaredField("mFlingRunnable");
            mFlingEndField.setAccessible(true);
            mFlingEndMethod = mFlingEndField.getType().getDeclaredMethod("endFling");
            mFlingEndMethod.setAccessible(true);
        } catch (Exception e) {
            mFlingEndMethod = null;
        }
    }

    public static void stop(ListView list) {
        if (mFlingEndMethod != null) {
            try {
                mFlingEndMethod.invoke(mFlingEndField.get(list));
            } catch (Exception e) {
            }
        }
    }
}

谢谢,这对我非常有用。原生的Android小部件也可以做到这一点(这只是一个猜测..):如果你把一个ListView放在ViewPager里面,然后滑动列表,再向左滑动,ViewPager将手动停止滚动。 - sydd
@arul 这就是完整的代码,只需在您的列表视图实例上使用此方法即可停止滚动。没有太多需要解释的。它使用反射来破解ListView的内部字段。无论如何,如果您的目标API >= 8,我建议先查看smoothScrollToPosition。 - Knickedi

3

您可以通过重写onTouchEvent方法并调用smoothScrollBy来防止API 8中ListView的滑动。

@Override
public boolean onTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_UP:
        this.smoothScrollBy(0, 0);
        break;
    }
    return super.onTouchEvent(ev);
}

这将取代快速滑动(fling scrolling)并代替为滚动0px。


3

当然有方法可以做到。但在我看来,更重要的是是否建议这样做。

列表是一个标准的Android控件,在所有应用程序中都表现出一致性。因此,如果我发现一个列表在您的应用程序中没有表现出相同的行为,我会感到惊讶。您可以随时将手指放回屏幕上来停止滑动。

话虽如此,如果您想要额外的工作,您可以子类化列表视图并覆盖其on touch方法。了解该怎么做的最好方法是获取ListView的源代码(Android 1.6中的ListView)。


1
我会 echo MarvinLabs 的评论,关于保持您的列表与用户 期望 它的工作方式一致。 - Mark Allison

0

我认为你不应该修改这个行为,因为用户期望的就是fling(迅速滑动)的效果。

但是,回答你的问题。虽然我没有尝试过,但从理论上讲它应该可以工作。

在你的ListView上实现一个OnScrollListener,并使用onScrollStateChanged()方法检查当前状态是否为SCROLL_STATE_FLING。确定滚动是由快速滑动执行后,您可以通过使用getFirstVisiblePosition()方法获取ListView的第一个可见位置,然后您可以使用smoothScorllToPosition(),将您的getFirstVisiblePosition()值作为参数放进去。


0
如果你想禁用列表视图的默认动画,只需要在XML中为根(主)布局设置id,并在根布局的类中调用void onClickListener

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