Determine When a Viewpager Changes Pages

Determine when a ViewPager changes pages

Use the ViewPager.onPageChangeListener:

viewPager.addOnPageChangeListener(new OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

public void onPageSelected(int position) {
// Check if this is the page you want.
}
});

Differentiating between user scroll and programatic page change in ViewPager

OK, so it turns out that I was right about the answer lying in ViewPager.onPageChangeListener. In particular it lies in using onPageScrollStateChanged(int state). Essentially there are three states that a page in a ViewPager can be in:

  1. Dragging: Indicates that the pager is currently being dragged by the user.
  2. Idle: Indicates that the pager is in an idle, settled state.
  3. Settling: Indicates that the pager is in the process of settling to a final position.

So the dragging state only occurs when the current page is being physically dragged by the user. Thus when the user has swiped a page the states occur in the following order: Dragging -> Settling -> Idle. Now, the onPageSelected(int position) method is called between the "Settling" and "Idle" states. Thus, in order to determine whether or not a page change was caused by a user scroll one just needs to check that the previous state was "dragging" and that the current state is "Settling". You can then keep a boolean variable to track whether or not the page change was user initiated or not and check it in your onPageSelected(int position) method.

Here is my onPageScrollStateChanged method

public void onPageScrollStateChanged(int state) 
{
if (previousState == ViewPager.SCROLL_STATE_DRAGGING
&& state == ViewPager.SCROLL_STATE_SETTLING)
userScrollChange = true;

else if (previousState == ViewPager.SCROLL_STATE_SETTLING
&& state == ViewPager.SCROLL_STATE_IDLE)
userScrollChange = false;

previousState = state;
}

The if and else if statements need not be so explicit but I did so for clarity.

Is there a way to check whether ViewPager is currently scrolling between pages?

The solution I found allows me to identify whether there is a scroll in progress. scrollState has three values defined in ViewPager: SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING and SCROLL_STATE_SETTLING. Now I can check scrollState in the onTouch method and act accordingly.

@Override
public void onPageScrollStateChanged(int state) {
scrollState=state;
}

Detect ViewPager tab change inside Fragment

I did some digging and it turns out that ViewPager will call both: setUserVisibleHint and setMenuVisibility. I would override setUserVisibleHint since the documentation for setUserVisibleHint states:

Set a hint to the system about whether this fragment's UI is currently visible to the user. This hint defaults to true and is persistent across fragment instance state save and restore.
An app may set this to false to indicate that the fragment's UI is scrolled out of visibility or is otherwise not directly visible to the user. This may be used by the system to prioritize operations such as fragment lifecycle updates or loader ordering behavior.

Try putting this code in your fragment:

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);

// Make sure that we are currently visible
if (this.isVisible()) {
// If we are becoming invisible, then...
if (!isVisibleToUser) {
Log.d("MyFragment", "Not visible anymore. Stopping audio.");
// TODO stop audio playback
}
}
}

How to determine when Fragment becomes visible in ViewPager

How to determine when Fragment becomes visible in ViewPager

You can do the following by overriding setUserVisibleHint in your Fragment:

public class MyFragment extends Fragment {
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
}
else {
}
}
}


Related Topics



Leave a reply



Submit