Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
241 views
in Technique[技术] by (71.8m points)

android - Sync Two ScrollView

Situation: I have two ScrollView inside of each of two HorizontalScrollView of a TableRow.

Goal: When I touch drag one of ScrollView, another ScrollView must scroll as much. For instance, if I have a list of name on left ScrollView and corresponding phone numbers in right ScrollView, scrolling one ScrollView should not destroy the original bounding between the names and phone numbers.

Can it be implemented by onTouchEvent? If so, how should I implement this(on both or one of the ScrollView)?

Please help me out Android Gurus!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I have a simple solution that works for me:

  • subclass both ScrollViews and override their onScrollChanged event to update ScrollManager when scrolling changes:

    public interface ScrollNotifier {   
        public void setScrollListener(ScrollListener scrollListener);
    
        public ScrollListener getScrollListener();
    }
    
    public class SyncedScrollView extends ScrollView implements ScrollNotifier {
    
        //...
    
        private ScrollListener scrollListener = null;
    
        @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
            if (scrollListener != null)
                scrollListener.onScrollChanged(this, l, t, oldl, oldt);
        }
        @Override
        public void setScrollListener(ScrollListener scrollListener) {
            this.scrollListener = scrollListener;
        }
        @Override
        public ScrollListener getScrollListener() {
            return scrollListener;
        }
    }
    
  • create a ScrollManager class that coordinates the scrolling of multiple participants

    public interface ScrollListener {
        void onScrollChanged(View syncedScrollView, int l, int t, int oldl,
            int oldt);
    }
    
    public class ScrollManager implements ScrollListener {
        private static final int SCROLL_HORIZONTAL = 1;
        private static final int SCROLL_VERTICAL = 2;
    
        private ArrayList<ScrollNotifier> clients = new ArrayList<ScrollNotifier>(4);
    
        private volatile boolean isSyncing = false;
        private int scrollType = SCROLL_HORIZONTAL;
    
        public void addScrollClient(ScrollNotifier client) {
            clients.add(client);
            client.setScrollListener(this);
        }
    
        // TODO fix dependency on all views being of equal horizontal/ vertical
        // dimensions
        @Override
        public void onScrollChanged(View sender, int l, int t, int oldl, int oldt) {
            // avoid notifications while scroll bars are being synchronized
            if (isSyncing) {
                return;
            }
    
            isSyncing = true;
    
            // remember scroll type
            if (l != oldl) {
                scrollType = SCROLL_HORIZONTAL;
            } else if (t != oldt) {
                scrollType = SCROLL_VERTICAL;
            } else {
                // not sure why this should happen
                isSyncing = false;
                return;
            }
    
            // update clients
            for (ScrollNotifier client : clients) {
                View view = (View) client;
                // don't update sender
                if (view == sender) {
                    continue;
                }
    
                // scroll relevant views only
                // TODO Add support for horizontal ListViews - currently weird things happen when ListView is being scrolled horizontally
                if ((scrollType == SCROLL_HORIZONTAL && view instanceof HorizontalScrollView)
                        || (scrollType == SCROLL_VERTICAL && view instanceof ScrollView)
                        || (scrollType == SCROLL_VERTICAL && view instanceof ListView)) {
                    view.scrollTo(l, t);
                }
            }
    
            isSyncing = false;
        }
    }
    
  • create the custom ScrollViews and set the ScrollManager for notification on both

    private void setupScrolling() {
        ScrollNotifier view;
        ScrollManager scrollManager = new ScrollManager();
    
        // timeline horizontal scroller
        view = (ScrollNotifier) findViewById(R.id.epgtimeline_container);
        scrollManager.addScrollClient(view);
    
        // services vertical scroller
        view = (ScrollNotifier) findViewById(R.id.epgservices_container);
        scrollManager.addScrollClient(view);
    
        // content area scrollers
        view = (ScrollNotifier) findViewById(R.id.epgevents_container_inner);
        scrollManager.addScrollClient(view);
        view = (ScrollNotifier) findViewById(R.id.epgevents_container_outer);
        scrollManager.addScrollClient(view);
    }
    

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...