Search code examples
androidandroid-scrollview

Scrolling parallel views simultaneously


I have two ScrollView's side by side and by using the code below I can scroll them simultaneously but I still can scroll them each independently throwing off the scroll positions. How can I make each view scroll simultaneously and disable scrolling each view by itself? I apologize if there's any confusion in my question. Any help would be appreciated, thanks.

ScrollView sv1;
ScrollView sv2;
View clickSource;
View touchSource; 

   sv1.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(touchSource == null)
                touchSource = v;

            if(v == touchSource) {
                sv2.dispatchTouchEvent(event);
                if(event.getAction() == MotionEvent.ACTION_UP) {
                    clickSource = v;
                    touchSource = null;
                }
            }

            return false;
        }
    });
    sv2.setOnTouchListener(new View.OnTouchListener(){
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(touchSource == null)
                touchSource = v;

            if(v == touchSource) {
                sv1.dispatchTouchEvent(event);
                if(event.getAction() == MotionEvent.ACTION_UP) {
                    clickSource = v;
                    touchSource = null;
                }
            }

            return false;
        }
    });

Solution

  • Hopefully I understand your question correctly. If you want both ScrollViews to scroll simultaneously then the code below should do the trick (untested):

    First create an interface to listen to scroll events:

    public interface ScrollChangeListener {
    
        public void onScrollChanged(View view, int x, int y, int oldx, int oldy);
    }
    

    Next, create a custom view so you can listen for scroll changes:

    public class ObservableScrollView extends ScrollView {
    
        private ScrollChangeListener mScrollChangeListener;
    
        public ObservableScrollView(Context context) {
            super(context);
        }
    
        public ObservableScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public ObservableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public ObservableScrollView(Context context, AttributeSet attrs, int defStyleAttr,
                                    int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        public void setScrollChangeListener(ScrollChangeListener listener) {
            mScrollChangeListener = listener;
        }
    
        @Override
        protected void onScrollChanged(int x, int y, int oldx, int oldy) {
            if (mScrollChangeListener != null) {
                mScrollChangeListener.onScrollChanged(this, x, y, oldx, oldy);
            }
        }
    }
    

    Use your custom view and create a listener for both ScrollViews.

    ObservableScrollView mScrollView1;
    
    ObservableScrollView mScrollView2;
    
    ...
    
    ScrollChangeListener listener = new ScrollChangeListener() {
    
        @Override
        public void onScrollChanged(View view, int x, int y, int oldx, int oldy) {
            ScrollView scrollView;
            if (view == mScrollView1) {
                scrollView = mScrollView2;
            } else if (view == mScrollView2) {
                scrollView = mScrollView1;
            } else {
                return;
            }
            scrollView.scrollTo(x, y);
        }
    };
    
    ...
    
    mScrollView1.setScrollChangeListener(listener);
    mScrollView2.setScrollChangeListener(listener);