androidandroid-scrollview

How to stop scroll in progress in NestedScrollView?


I have a button to automatically returns to top position into a NestedScrollView. When the scroll is not in progress, it works like a charm, otherwise if the current scrolling is in progress yet, the scroll goes to top but directly scroll a lit bit down just after...

I wrote this method:

private void scrollToTop() {
        mScrollView.stopNestedScroll();
        mScrollView.postDelayed(new Runnable() {
            @Override
            public void run() {
                mScrollView.scrollTo(0, 0);
            }
        }, 50);
    }

Have you got some ideas guys to stop the current scroll and go to top immediately?

Thank you very much


Solution

  • The correct way would be intercepting user's touch when you scrolling pragmatically. That would require you to extend ScrollView overriding scrollTo and onInterceptTouchEvent methods and disable user touch while list is scrolling, returning touch after scroll is complete.

    So the sequence would be like this:

    1. Call scrollTo to scroll to specific position
    2. Enable a flag to disable touch events and begin scrolling
    3. When scroll is finished and state changed to idle disable flag

    P.S: I can provide code example but it appears you have more expertise than me in writing codes. Cheers!

    Here a code snippet:

    import android.content.Context;
    import android.support.v4.widget.NestedScrollView;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    
    public class MyScrollView extends NestedScrollView {
    
        public static final int MAX_SCROLL_FACTOR = 1;
        boolean isAutoScrolling;
    
        public MyScrollView(Context context) {
            super(context);
        }
    
        public MyScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        public void scrollTo(int x, int y) {
            isAutoScrolling = true;
            super.scrollTo(x, y);
        }
    
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {
            if (isAutoScrolling)
                return super.onInterceptTouchEvent(event);
    
            return false;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (isAutoScrolling)
                return super.onTouchEvent(event);
    
    
            return false;
        }
    
        @Override
        protected void onScrollChanged(int x, int y, int oldX, int oldY) {
            super.onScrollChanged(x, y, oldX, oldY);
            if (isAutoScrolling) {
                if (Math.abs(y - oldY) < MAX_SCROLL_FACTOR  || y >= getMeasuredHeight() || y == 0
                        || Math.abs(x - oldX) < MAX_SCROLL_FACTOR || x >= getMeasuredWidth() || x == 0) {
                    isAutoScrolling = false;
                }
            }
        }
    }