I want to stop NestedScrollview scrolling animation after fling and programmatically scroll to top smoothly. In my case SmoothScrollTo(0, 0) works correct but after it previous scrolling animation continued a little.
I found very similar question: How to stop scroll in progress in NestedScrollView?
But answer of Keivan Esbati doesn't work for me. Can anybody help me?
Programmatically called scroll to top:
public void ScrollToTop()
{
if (!IsOnTopOfScroll())
{
ObjectAnimator.OfInt(scrollView, "scrollY", scrollView.Top).SetDuration(150).Start();
}
}
Extended 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;
}
}