【问题标题】:How to stop NestedScrollView scrolling when SmoothScrollTo(0, 0) called调用 SmoothScrollTo(0, 0) 时如何停止 NestedScrollView 滚动
【发布时间】:2021-01-15 11:48:26
【问题描述】:

我想在投掷后停止 NestedScrollview 滚动动画并以编程方式平滑滚动到顶部。 在我的情况下,SmoothScrollTo(0, 0) 可以正常工作,但在它之前的滚动动画之后会继续一点。

我发现了非常相似的问题: How to stop scroll in progress in NestedScrollView?

但是Keivan Esbati 的回答对我不起作用。有人可以帮帮我吗?

以编程方式调用滚动到顶部:

    public void ScrollToTop()
        {
            if (!IsOnTopOfScroll())
            {
                ObjectAnimator.OfInt(scrollView, "scrollY", scrollView.Top).SetDuration(150).Start();
            }
        }

扩展的 NestedScrollView:

public class ObservableNestedScrollView : NestedScrollView, IScrollable
{
        private const int MAX_SCROLL_FACTOR = 1;
        private bool isAutoScrolling;

        public override void ScrollTo(int x, int y)
        {
            isAutoScrolling = true;
            base.ScrollTo(x, y);
        }

      public override bool OnInterceptTouchEvent(MotionEvent ev)
        {
            if (isAutoScrolling)
            {
                return base.OnTouchEvent(ev);
            }

            if (hasNoCallbacks())
            {
                return base.OnInterceptTouchEvent(ev);
            }
            switch (ev.ActionMasked)
            {
                case MotionEventActions.Up:
                case MotionEventActions.Cancel:
                    mDragging = false;
                    DispatchOnUpOrCancelMotionEvent(mScrollState);
                    return false;
                case MotionEventActions.Down:
                    mFirstScroll = mDragging = true;
                    DispatchOnDownMotionEvent();
                    break;
            }
            return base.OnInterceptTouchEvent(ev);
        }

        public override bool OnTouchEvent(MotionEvent ev)
        {
            if (isAutoScrolling)
            {
                return base.OnTouchEvent(ev);
            }

            if (hasNoCallbacks())
            {
                return base.OnTouchEvent(ev);
            }

            switch (ev.ActionMasked)
            {
                case MotionEventActions.Up:
                case MotionEventActions.Cancel:
                    mIntercepted = false;
                    mDragging = false;
                    DispatchOnUpOrCancelMotionEvent(mScrollState);
                    break;
                case MotionEventActions.Move:
                    if (mPrevMoveEvent == null)
                    {
                        mPrevMoveEvent = ev;
                    }
                    float diffY = ev.GetY() - mPrevMoveEvent.GetY();
                    mPrevMoveEvent = MotionEvent.ObtainNoHistory(ev);
                    if (GetCurrentScrollY() - diffY <= 0)
                    {

                        if (mIntercepted)
                        {
                            return false;
                        }

                        ViewGroup parent;
                        if (mTouchInterceptionViewGroup == null)
                        {
                            parent = (ViewGroup)Parent;
                        }
                        else
                        {
                            parent = mTouchInterceptionViewGroup;
                        }

                        float offsetX = 0;
                        float offsetY = 0;
                        for (View v = this; v != null && v != parent; v = (View)v.Parent)
                        {
                            offsetX += v.Left - v.ScrollX;
                            offsetY += v.Top - v.ScrollY;
                        }

                        MotionEvent mEvent = MotionEvent.ObtainNoHistory(ev);
                        mEvent.OffsetLocation(offsetX, offsetY);

                        if (parent.OnInterceptTouchEvent(mEvent))
                        {
                            mIntercepted = true;

                            mEvent.Action = MotionEventActions.Down;

                            Post(new RunnableAnonymousInnerClassHelper(parent, mEvent));
                            return false;
                        }
                        return base.OnTouchEvent(ev);
                    }
                    break;
            }

            return base.OnTouchEvent(ev);
        }

        protected override void OnScrollChanged(int x, int y, int oldX, int oldY)
        {
            base.OnScrollChanged(x, y, oldX, oldY);

            if (isAutoScrolling)
            {
                if (System.Math.Abs(y - oldY) < MAX_SCROLL_FACTOR || y >= MeasuredHeight || y == 0
                        || System.Math.Abs(x - oldX) < MAX_SCROLL_FACTOR || x >= MeasuredWidth || x == 0)
                {
                    isAutoScrolling = false;
                }
            }

            if (hasNoCallbacks())
            {
                return;
            }
            mScrollY = y;

            DispatchOnScrollChanged(y, mFirstScroll, mDragging);
            if (mFirstScroll)
            {
                mFirstScroll = false;
            }

            if (mPrevScrollY < y)
            {
                mScrollState = ScrollState.UP;
            }
            else if (y < mPrevScrollY)
            {
                mScrollState = ScrollState.DOWN;
                //} else {
            }
            mPrevScrollY = y;
        }
}

【问题讨论】:

  • 我试图重现您的问题,但我缺少有关IScrollableDispatchOnUpOrCancelMotionEventDispatchOnDownMotionEventGetCurrentScrollY 的部分代码您能分享这些代码吗?提供可以重现此问题的演示更好,
  • @LeonLu-MSFT 我在 GitHub 上创建了演示项目 TestNestedScrollView

标签: android xamarin android-nestedscrollview


【解决方案1】:

首先,我看到您的项目仍在使用 Android 支持包,请升级它们以使用 AndroidX 以获得更好的体验。您可以参考AndroidX migration in Xamarin.Forms了解更多信息,它还包括如何迁移包。

我检查了另一个线程并尝试了一个干净的演示,但它也不适合我,但我确实找到了另一个适合我的建议:https://stackoverflow.com/a/59333212/12936075

您可以制作您的 FabOnClick:

    private void FabOnClick(object sender, EventArgs eventArgs)
    {
        scrollView.Fling(0);
        scrollView.SmoothScrollTo(0, 0);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-19
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 2016-06-22
    • 1970-01-01
    • 2019-10-27
    相关资源
    最近更新 更多