Getting the current position of a ViewPager

AndroidAndroid Viewpager

Android Problem Overview


I know with the Gallery widget I was able to use getSelectedItemPosition(); to retrieve the current position, however it doesnt seem ViewPager has that.

I know I can setup a listener and retrieve the position when the page is switched. But I want the current view position.

Android Solutions


Solution 1 - Android

You can use:

mViewPager.getCurrentItem()

Solution 2 - Android

Create a listener and set it on your viewpager:

/**
 * Get the current view position from the ViewPager by
 * extending SimpleOnPageChangeListener class and adding your method
 */
public class DetailOnPageChangeListener extends ViewPager.SimpleOnPageChangeListener {

	private int currentPage;

	@Override
	public void onPageSelected(int position) {
	    currentPage = position;
	}

	public final int getCurrentPage() {
	    return currentPage;
	}
}

Solution 3 - Android

Update 2019

Now you can set addOnPageChangeListener on View Pager to Observe change in Page position.

Since you wanted to setup a listener and retrieve the position when the page is switched

mViewPager.addOnPageChangeListener(object : OnPageChangeListener {
            override fun onPageScrollStateChanged(state: Int) {}
            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}

            override fun onPageSelected(position: Int) {
                pagePosition.setText("" + position + "/" + galleryAdapter!!.count)
            }
        })

Solution 4 - Android

My solution would only work if you have a TabLayout linked to your ViewPager.

This is how they're linked:

tabLayout.setupWithViewPager(viewPager);

And then to get current position, you can make use of:

tabLayout.getSelectedTabPosition()

Solution 5 - Android

I'm telling you now its a hack, so there is no reason to downvote for that reason. Meaning, it either will be helpful to you specifically or not. Either way, the description below will provide some insight and be helpful to the community. Also, this solution is good for the older APIs that don't have ViewPager.getCurrentItem().


First, a little information. If you iterate thru all children of a ViewPager with ViewPager.getChildAt(x); and print out with toString() (or getLeft()) each child View (a page) and then do this everytime you change pages, you will notice that the children will not be in the logical order that they are displayed in when you start going back pages (paging back to the beginning). Apparently, it will remove the unneeded child from the array then append the newest child to the array. So, for example, lets say you are looking at page 2 then changed to page 3, your list of children will be in this order page 2, page 3, page 4 meaning that ViewPager.getChildAt(1); will return the current page. But, if you then change back to page 2 (from page 3) your list of children will be in this order page 2, page 3, page 1 which means that ViewPager.getChildAt(1); does not return the current page. I have not yet been able to find simple logic to weed out the current page using this information. Because the order of the pages in the array behind getChildAt is in an arbitrary order based off of how the user has been paging around.

That being said, I developed a hack work-around. I have no clue if this function will work in all in environments, but it works for my current project. I would suspect if doesn't for you, then its an issue of different API level. But I dont actually suspect any issues for other environments.

Now, onto the meat. What I noticed was that the result of ViewPager.getChildAt(x).getLeft() will have some type of horizontal pixel coordinate relative to the parent. So, I used this information to weed out which view is the current one.

private int getCurrentPageIndex(ViewPager vp){
    int first,second,id1,id2,left;
    id1 = first = second = 99999999;
    View v;
    for ( int i = 0, k = vp.getChildCount() ; i < k ; ++i ) {
        left = vp.getChildAt(i).getLeft();
        if ( left < second ) {
            if ( left < first ) {
                second = first;
                id2 = id1;
                first = left;
                id1 = i;
            } else {
                second = left;
                id2 = i;
            }
        }
    }
    return id2;
}

This function is probably a questionable hack because it relies on the value of getLeft() to figure it all out. But, I grab the left coordinate of each child. I then compare this to the other values and store the first and second pages, returning the second page (current page) out of the function. It seems to work beautifully.

Why (might you ask) didn't I just use onClickListenter or whatever solution? Well, I was darned determined that there was a straight forward way to do this without having to include listeners, other classes, inconclusive focus, and other bloat. Unfortunately, this solution is not exactly straight forward. But, it does do away with the bloat, other classes and listeners. If I can figure out a more straight forward way, I will be rewriting this function. Or maybe, this will provide insight for someone else to have an epiphany.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAdamView Question on Stackoverflow
Solution 1 - AndroidTerryView Answer on Stackoverflow
Solution 2 - AndroidandroiduView Answer on Stackoverflow
Solution 3 - AndroidHitesh SahuView Answer on Stackoverflow
Solution 4 - AndroidHulisani MudimeliView Answer on Stackoverflow
Solution 5 - AndroidPimp TrizkitView Answer on Stackoverflow