问题描述
我想在滑动后停止 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();
}
}
扩展的嵌套滚动视图:
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;
}
}
解决方法
首先,我看到您的项目仍在使用 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);
}