Android horizontal scrollview behave like iPhone (paging)
Asked Answered
P

4

31

I have a LinearLayout inside a HorizontalScrollView. The content is just a image. While scrolling, I need to achieve the same behavior you get when setting the paging option on a the iPhone equivalent of the HSW (scrolling the list should stop at every page on the list, not continue moving).

How is this done in Android? Should I implement this features by myself or there is a particular property to set or a subclass of HSV to implement?

Positive answered 7/4, 2010 at 18:51 Comment(1)
Check this tutorial, it works and is really simple for an horizontal paging: http://mobile.tutsplus.com/tutorials/android/android-user-interface-design-horizontal-view-paging/Landgrave
P
15

So, my solution is:

  1. Intercept the onTouch event and calculate whether the page should change to the next or keep on the current
  2. Inherit from HorizontalScrollView and override the method computeScroll

The method computeScroll the called to move the list. By default I suppose it's implemented to decelerate with a certain ratio... Since I don't want this motion, I just override it without specifing a body.

The code for the event handler is:

_scrollView.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_UP)
            {
                float currentPosition = _scrollView.getScrollX();
                float pagesCount = _horizontalBar.getChildCount();
                float pageLengthInPx = _horizontalBar.getMeasuredWidth()/pagesCount;
                float currentPage = currentPosition/pageLengthInPx;

                Boolean isBehindHalfScreen =  currentPage-(int)currentPage > 0.5;

                float edgePosition = 0;
                if(isBehindHalfScreen)
                {
                    edgePosition = (int)(currentPage+1)*pageLengthInPx;
                }
                else
                {
                    edgePosition = (int)currentPage*pageLengthInPx;
                }

                _scrollView.scrollTo((int)edgePosition, 0);
            }

            return false;
        }
    });

And in my inherited HorizontalScrollView

@Override
    public void  computeScroll  (){
        return;
    }
Positive answered 8/4, 2010 at 9:52 Comment(1)
Sorry but I can't remember. It an old question sorry :(Positive
P
20

I came across a nice solution here:

Horizontal Pager

this is a cleaned up GitHub version of the code found here:

Real View Switcher

It may seem like overkill for just using it on images, but this solution allows for infinite paging with using a little trick (ie: when on first page you can scroll back to last page and when on last page you can scroll forward to first page). It also allows you to have an unknown number of pages and dynamically generate content by using another little trick. Please see my comment in the second link here

for details on how i accomplished this.

Hope this helps.

Pita answered 16/3, 2011 at 21:17 Comment(2)
the problem with Horizontal Page or Real View Switcher is that if you add a ListView as a child, and the ListView does not exceed the screen's height, the space in between (the last row of the ListView to the end of the screen) is filled with "white" or a transparent background. any ideas around this issue?Plutonian
This is obsolete with ViewPagerScherzo
P
15

So, my solution is:

  1. Intercept the onTouch event and calculate whether the page should change to the next or keep on the current
  2. Inherit from HorizontalScrollView and override the method computeScroll

The method computeScroll the called to move the list. By default I suppose it's implemented to decelerate with a certain ratio... Since I don't want this motion, I just override it without specifing a body.

The code for the event handler is:

_scrollView.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_UP)
            {
                float currentPosition = _scrollView.getScrollX();
                float pagesCount = _horizontalBar.getChildCount();
                float pageLengthInPx = _horizontalBar.getMeasuredWidth()/pagesCount;
                float currentPage = currentPosition/pageLengthInPx;

                Boolean isBehindHalfScreen =  currentPage-(int)currentPage > 0.5;

                float edgePosition = 0;
                if(isBehindHalfScreen)
                {
                    edgePosition = (int)(currentPage+1)*pageLengthInPx;
                }
                else
                {
                    edgePosition = (int)currentPage*pageLengthInPx;
                }

                _scrollView.scrollTo((int)edgePosition, 0);
            }

            return false;
        }
    });

And in my inherited HorizontalScrollView

@Override
    public void  computeScroll  (){
        return;
    }
Positive answered 8/4, 2010 at 9:52 Comment(1)
Sorry but I can't remember. It an old question sorry :(Positive
G
15

The new Compatibility Package (revision 3) in Android added a ViewPager which does that.

http://developer.android.com/sdk/compatibility-library.html

Guglielmo answered 19/7, 2011 at 5:35 Comment(2)
ViewPager docs are here: developer.android.com/reference/android/support/v4/view/…Flatfoot
ViewPager tutorial here: developer.android.com/training/animation/screen-slide.htmlFlatfoot
E
0

i found another way to get the same effect and i think is more readable. Here is the way:

@Override
        public boolean onTouch(View v, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_UP)
            {
                float currentPosition = hsv.getScrollX();
                float pagesCount = hsv.getChildCount();
                float pageLengthInPx = hsv.getMeasuredWidth()/pagesCount;

                int page = (int) (Math.floor((currentPosition - pageLengthInPx / 2) / pageLengthInPx) + 1);
                hsv.scrollTo((int) (page * pageLengthInPx), 0);
            }

            return false;
        }
Elanorelapid answered 14/3, 2012 at 21:21 Comment(2)
Where hsv is the object HorizontalScrollView :PElanorelapid
I think that the HorizontalScrollView will only accept one child, which is some kind of Layout Group... this group is where the children will be added so it is from there that the number of them will be retrieved.Gastro

© 2022 - 2024 — McMap. All rights reserved.