我重写了ScrollView,将MotionEvent传递给GestureDetector,以检测ScrollView上的猛击事件。我需要能够检测滚动停止的时间。这与MotionEvent.ACTION_UP事件不一致,因为这通常发生在猛击手势开始时,随后在ScrollView上出现一连串的onScrollChanged()调用。

因此,基本上,我们在这里处理的是以下事件:

  • onFling
  • onScrollChanged,onScrollChanged,onScrollChanged,...,onScrollChanged

  • 当onScrollChanged事件完成触发时,没有回调。我当时在考虑在onFling期间使用Handler将消息发布到事件队列,并等待Runnable执行以指示猛击结束,但不幸的是,它在第​​一个onScrollChanged调用后触发。

    还有其他想法吗?

    最佳答案

    我结合了here的一些答案,以构造一个类似于AbsListView的工作监听器。从本质上讲,这就是您所描述的内容,并且在我的测试中效果很好。

    注意:您可以简单地覆盖ScrollView.fling(int velocityY)而不是使用自己的GestureDetector

    import android.content.Context;
    import android.util.AttributeSet;
    import android.widget.ScrollView;
    
    public class CustomScrollView extends ScrollView {
    
        private static final int DELAY_MILLIS = 100;
    
        public interface OnFlingListener {
            public void onFlingStarted();
            public void onFlingStopped();
        }
    
        private OnFlingListener mFlingListener;
        private Runnable mScrollChecker;
        private int mPreviousPosition;
    
        public CustomScrollView(Context context) {
            this(context, null, 0);
        }
    
        public CustomScrollView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
            mScrollChecker = new Runnable() {
                @Override
                public void run() {
                    int position = getScrollY();
                    if (mPreviousPosition - position == 0) {
                        mFlingListener.onFlingStopped();
                        removeCallbacks(mScrollChecker);
                    } else {
                        mPreviousPosition = getScrollY();
                        postDelayed(mScrollChecker, DELAY_MILLIS);
                    }
                }
            };
        }
    
        @Override
        public void fling(int velocityY) {
            super.fling(velocityY);
    
            if (mFlingListener != null) {
                mFlingListener.onFlingStarted();
                post(mScrollChecker);
            }
        }
    
        public OnFlingListener getOnFlingListener() {
            return mFlingListener;
        }
    
        public void setOnFlingListener(OnFlingListener mOnFlingListener) {
            this.mFlingListener = mOnFlingListener;
        }
    
    }
    

    10-05 18:01