1

My ultimate goal is to stop the scroll in specific locations, so the objects being viewed are shown completely, and the solution I came up with is by checking the scrollX location of the view when the touch is released. I did have a momentum issue, as the scroll could still continue due to the scroll velocity also after catching the touch event, I solved that using MotionEvent.ACTION_CANCEL, which I am not happy with, as the scrollTo is optically pleasing, but the MotionEvent.ACTION_CANCEL kills its effect.

My question is, is there a more elegant way to do this? Ideal would be if I could simply instruct my ScrollView NOT to have momentum/velocity.

    myView.setOnTouchListener(new HorizontalScrollView.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                event.setAction(MotionEvent.ACTION_CANCEL);
                int x = myView.getScrollX();
                if (x < 150)
                    myView.scrollTo(0,0);
                else if (x<450)
                    myView.scrollTo(300,0);
                else
                    myView.scrollTo(600,0);
            }
            return false;
        }
    });
Gil
  • 25
  • 9

2 Answers2

0

If you want to scroll precisely to show specific view, this answer should help you. What you have to do is to call myView.scrollTo(0, view.getBottom()) or myView.smoothScrollTo(0, view.getBottom()) on UI thread. This way, view object will be displayed fully.


EDIT: It seems to me that what you're trying to achieve here is very close to what ViewPager does: your intention is to move between the views with a swipe/fling gesture, providing full visibility to the paged views contents.

If you were to use ViewPager, this is how your code may have looked:

viewPager.setAdapter(new PagerAdapter() {

            @Override
            public boolean isViewFromObject(View view, Object object) {
                return view == object;
            }

            @Override
            public int getCount() {
                return getViewCount();
            }

            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                View view = getViewAtPosition(position);
                container.addView(view);
                return view;
            }

            @Override
            public void destroyItem(ViewGroup container, int position, Object view) {
                container.removeView((View) view);
            }
        });

Where getViewCount() and getViewAtPosition() methods have to be implemented accordingly to how many displayed views you want and the way they are instantiated.

Community
  • 1
  • 1
archived
  • 647
  • 8
  • 24
  • Thanks, this aspect I am ok with. I have more difficulty with the fact that the method you describe does not work well when applied using OnTouchListener, as residual scrolling could occur due to scroll velocity after calling the focusing method. – Gil Mar 03 '16 at 17:27
  • Thank you, this ViewPager seems to be the function I was looking for. – Gil Mar 04 '16 at 21:58
0

You should use an onScrollListener if you want to get the current position when the scrollView is scrolled.

scrollView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {

    @Override
    public void onScrollChanged() {

        int scrollX = rootScrollView.getScrollX(); //for horizontalScrollView
        int scrollY = rootScrollView.getScrollY(); //for verticalScrollView
        //DO SOMETHING WITH THE SCROLL COORDINATES

    }
});
Niza Siwale
  • 2,390
  • 1
  • 18
  • 20