简体   繁体   English

检测ScrollView上的结束

[英]Detect end of fling on ScrollView

I've overridden ScrollView to pass MotionEvent s to a GestureDetector to detect fling events on the ScrollView. 我重写ScrollView通过MotionEvent s到一个GestureDetector来检测了滚动一扔事件。 I need to be able to detect when the scrolling stops. 我需要能够检测到滚动停止的时间。 This doesn't coincide with the MotionEvent.ACTION_UP event because this usually happens at the start of a fling gesture, which is followed by a flurry of onScrollChanged() calls on the ScrollView. 这与MotionEvent.ACTION_UP事件不一致,因为这通常发生在onScrollChanged()手势的开始,随后是ScrollView上的一连串onScrollChanged()调用。

So basically what we are dealing with here is the following events: 所以基本上我们在这里处理的是以下事件:

  1. onFling onFling
  2. onScrollChanged, onScrollChanged, onScrollChanged, ... , onScrollChanged onScrollChanged,onScrollChanged,onScrollChanged,...,onScrollChanged

There's no callback for when the onScrollChanged events are done firing. 触发onScrollChanged事件时没有回调。 I was thinking of posting a message to the event queue using a Handler during onFling and waiting for the Runnable to execute to signal the end of the fling, unfortunately it fires after the first onScrollChanged call. 我想在onFling期间使用Handler向事件队列发送消息,并等待Runnable执行以指示fling的结束,不幸的是它在第一次onScrollChanged调用之后触发。

Any other ideas? 还有其他想法吗?

I've combined a few of the answers from here to construct a working listener that resembles the way AbsListView does it. 我结合了这里的一些答案来构建一个类似于AbsListView的工作方式的工作监听器。 It's essentially what you describe, and it works well in my testing. 它基本上就是你所描述的,它在我的测试中运作良好。

Note: you can simply override ScrollView.fling(int velocityY) rather than use your own GestureDetector . 注意:您可以简单地覆盖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;
    }

}

Thank you @PaulBurke +1 谢谢@PaulBurke +1

Xamarin Solution Xamarin解决方案

using Android.Content;
using Android.Runtime;
using Android.Util;
using Android.Widget;
using System;

public class CustomScrollView : ScrollView
{
    public event EventHandler FlingEnded;
    public event EventHandler FlingStarted;

    private Action ScrollChecker;
    private int PreviousPosition;
    private const int DELAY_MILLIS = 100;

    public CustomScrollView(Context context) : base(context) => Init();
    public CustomScrollView(Context context, IAttributeSet attrs) : base(context, attrs) => Init();
    public CustomScrollView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr) => Init();
    public CustomScrollView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes) => Init();
    public CustomScrollView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }

    private void Init()
    {
        ScrollChecker = () =>
        {
            int position = ScrollY;
            if (PreviousPosition - position == 0)
            {
                FlingEnded?.Invoke(this, new EventArgs());
                RemoveCallbacks(ScrollChecker);
            }
            else
            {
                PreviousPosition = ScrollY;
                PostDelayed(ScrollChecker, DELAY_MILLIS);
            }
        };
    }

    public override void Fling(int velocityY)
    {
        base.Fling(velocityY);

        FlingStarted?.Invoke(this, new EventArgs());
        Post(ScrollChecker);
    }
}

Usage: 用法:

myCustomScrollView.FlingEnded += myCustomScrollView_FlingEnded;

protected void myCustomScrollView_FlingEnded(object sender, EventArgs e) =>
{
    //Do onFlingEnded code here
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM