停止 ListView 滚动动画

Posted

技术标签:

【中文标题】停止 ListView 滚动动画【英文标题】:Stop ListView scroll animation 【发布时间】:2011-09-16 04:53:32 【问题描述】:

我有一个ListView,大约有 100 个条目。当用户从下到上“滑动”时,它开始滚动并继续滚动,即使手指不再触摸显示屏。

此时有没有办法停止滚动动画?

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

这是正确的答案。这应该被接受,因为它无需反思即可工作。不错的工作伙伴!【参考方案2】:

我没有尝试Pompe de velo 的解决方案,但由于smoothScrollToPosition() 不适用于低于 8 的 API 级别,这对我不起作用。

我同意,更改默认行为不是一个好主意,但有时您需要这样做。所以这是我使用反射的(脏)解决方案。到目前为止,这不是推荐的方式,因为它是一种 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 中并翻转列表,然后向左滑动,pager 将手动停止滚动。 @arul 这是完整的代码,只需在列表视图实例上使用此方法即可停止滚动。没什么好解释的。它使用反射来破解 ListView 的内部字段。无论如何,如果您的目标 API >= 8,我建议您先看看 smoothScrollToPosition。【参考方案3】:

当然有办法做到这一点。但在我看来,更重要的是是否建议这样做。

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

也就是说,如果您想做额外的工作,您可以子类化列表视图并覆盖其 on touch 方法。最好的方法是获取 ListView 的源代码 (ListView in Android 1.6)。

【讨论】:

我会回应 MarvinLabs 的评论,即让您的列表与用户期望它的工作方式保持一致。【参考方案4】:

您可以通过重写 onTouchEvent 并调用 smoothScrollBy 来防止 API 8 中的 ListViews 被丢弃。

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

这会取代快速滚动并滚动 0px。

【讨论】:

【参考方案5】:

我的意见是你不应该修改这种行为,因为投掷行为是用户所期望的。

但是,对于您的问题。我还没有尝试过,但理论上它应该可以工作。

为您的ListView 实现OnScrollListener 并使用onScrollStateChanged() 方法检查当前状态是否为SCROLL_STATE_FLING。在您确定滚动执行后,您可以使用getFirstVisiblePosition() 方法获得ListView 的第一个可见位置,然后您可以使用smoothScrollToPosition() 在其中输入getFirstVisiblePosition() 值作为一个论点。

【讨论】:

【参考方案6】:

如果您从列表视图中禁用默认动画,只需在 xml 中为根(主)布局设置 id 并在类中为根布局调用 void onClickListener

【讨论】:

以上是关于停止 ListView 滚动动画的主要内容,如果未能解决你的问题,请参考以下文章

ListView 项目滚动动画(类似“UIKit Dynamics”)

在 Flutter 中向下滚动 ListView.builder 时出现不需要的动画

Flutter ListView 滚动动画重叠兄弟小部件

当您一直滚动到 ListView.builder 的顶部时,如何禁用动画

当代表具有不同的宽度时,QML ListView 滚动不会产生任何动画

Flutter - 与子小部件交互时停止 ListView 滚动