Skip to content

Instantly share code, notes, and snippets.

@Mercandj
Last active April 19, 2019 09:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mercandj/26493abcc810bade469386d6d77154d5 to your computer and use it in GitHub Desktop.
Save Mercandj/26493abcc810bade469386d6d77154d5 to your computer and use it in GitHub Desktop.
Android ViewPager: listen displayed step

ViewPager

Track ViewPager position


drawing drawing


  • Context: To welcome users, sucession of screens are displayed. Swipe horizontally or click on a "NEXT" button allows users to move from one screen to another.
  • Goal: Track the screen displays and send event on each step display to measure user behaviour.
  • HowTo:
    • Use Android ViewPager to have horizontal scrollable screens
    • Implement buttons that will call ViewPager.setCurrentItem(currentPosition + 1)
    • Listen current item changes on ViewPager with the listener ViewPager.OnPageChangeListener attached to the ViewPager instance.
new ViewPager.OnPageChangeListener() {

    /**
     * This method will be invoked when the current page is scrolled, either as part
     * of a programmatically initiated smooth scroll or a user initiated touch scroll.
     *
     * @param position Position index of the first page currently being displayed.
     *                 Page position+1 will be visible if positionOffset is nonzero.
     * @param positionOffset Value from [0, 1) indicating the offset from the page at position.
     * @param positionOffsetPixels Value in pixels indicating the offset from position.
     */
    @Override
    public void onPageScrolled(
            int position,
            float positionOffset,
            int positionOffsetPixels
    ) { }

    /**
     * This method will be invoked when a new page becomes selected. Animation is not
     * necessarily complete.
     *
     * @param position Position index of the new selected page.
     */
    @Override
    public void onPageSelected(
            @IntRange(from = 0) int position
    ) { }
    
    /**
     * Called when the scroll state changes. Useful for discovering when the user
     * begins dragging, when the pager is automatically settling to the current page,
     * or when it is fully stopped/idle.
     *
     * @param state The new scroll state.
     * @see ViewPager#SCROLL_STATE_IDLE
     * @see ViewPager#SCROLL_STATE_DRAGGING
     * @see ViewPager#SCROLL_STATE_SETTLING
     */
    @Override
    public void onPageScrollStateChanged(int state) { }
};

To listen screens displays, the instinctive solution is to use the onPageSelected(int) callback and send the event like that:

@Override
public void onPageSelected(
        @IntRange(from = 0) int position
) {
    eventManager.sendOnBoardingPageDisplay(position);
}

This solution will works and events will be sent when page is selected.

However, double clicks on "NEXT" buttons will have unwanted event sent. Indeed, the first click will set the current item position and start the ViewPager scroll annimation to the next screen. The second anywhere on the screen will interrupt the scroll and user will stay on the same screen.

drawing

For instance, on the screen with a 0 position, double click on the first "NEXT" button will not change the screen display and call:

eventManager.sendOnBoardingPageDisplay(1);
eventManager.sendOnBoardingPageDisplay(0);

The implementation should have use the onPageScrolled(int, float, int) position instead to send event based on the changes of the int position. (diable button double clicks is another solution)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment