How to test if a fragment view is visible to the user?

59,899

Solution 1

You're right there is a better way to do this!

Have a look at the FragmentPagerAdapter javadoc online and you'll see there is a method setPrimaryItem(ViewGroup container, int position, Object object):void doing exactly what you need.

From the javadoc

public void setPrimaryItem (ViewGroup container, int position, Object object)

Called to inform the adapter of which item is currently considered to be the "primary", that is the one show to the user as the current page.

Parameters container The containing View from which the page will be removed. position The page position that is now the primary. object The same object that was returned by instantiateItem(View, int).

Note on scroll state

Now if you implement this and start debugging to get a feel of when exactly this is called you'll quickly notice this is triggered several times on preparing the fragment and while the user is swiping along.

So it might be a good idea to also attach a ViewPager.OnPageChangeListener and only do what has to be done once the viewpagers scroll state becomes SCOLL_STATE_IDLE again.

Solution 2

This is what I use to determine the visibility of a fragment.

private static boolean m_iAmVisible;

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

    if (m_iAmVisible) { 
        Log.d(localTAG, "this fragment is now visible");
    } else {  
        Log.d(localTAG, "this fragment is now invisible");
    }
}

Solution 3

For my purposes, it worked to use ViewPager.OnPageChangeListener.onPageSelected() in conjunction with Fragment.onActivityCreated() to perform an action when the Fragment is visible. Fragment.getUserVisibleHint() helps too.

Solution 4

What is wrong with using getView().isShown() to find out if a Fragment is actually visible?

Solution 5

isVisible() 

Can still return true even if the fragment is behind an activity.

I'm using the following:

if (getView() != null && getView().isShown()) {
//your code here
}
Share:
59,899
David S.
Author by

David S.

Senior software engineer with solid knowledge in data structure and algorithm. Familiar with Cloud-Native architecture. Proficient in developing using a wide variety of tools. Eager to learn new technologies.

Updated on July 05, 2022

Comments

  • David S.
    David S. about 2 years

    I have a ViewPager, each page is a Fragment view. I want to test if a fragment is in a visible region. the Fragment.isVisible only test

    • the fragment is attached to a activity
    • the fragment is set to visible
    • the fragment has been added to a view

    The ViewPager will create 3 (by default) fragment and all three of them meet the above criteria, but only one is actually visible to the user (the human eyes)

  • David S.
    David S. over 12 years
    This is what I am doing right now. I am just thinking if there's other ways. Thanks
  • Edison
    Edison about 11 years
    This does not work as per documentation: "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"
  • PeteH
    PeteH about 11 years
    Good solution (+1) but code can be simplified: public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); m_iAmVisible = false; //default to not visible if (isVisibleToUser) { m_iAmVisible = true; } }
  • Kasas
    Kasas almost 11 years
    simplified is: public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); m_iAmVisible = isVisibleToUser;}
  • Leonardo Pinto
    Leonardo Pinto over 10 years
    even simpler, getUserVisibleHint()
  • Someone Somewhere
    Someone Somewhere about 10 years
    this approach works great if one extends the Application class and has to test whether a particular UI is showing. I just ended up using several booleans to test whether the app was backgrounded, and whether a particular fragment was showing.
  • David S.
    David S. about 9 years
    Have you tested your idea? I think this post pointed out the same idea.
  • awy
    awy about 9 years
    Yes. It works for me, as suggested in the linked post.
  • Lazar Kukolj
    Lazar Kukolj about 8 years
    THIS HELPS A LOT THANK YOU!
  • Mysterious_android
    Mysterious_android over 5 years
    according to this , isShown is similar to getVisibility() so it can still return true if VISIBLE but behind an activity
  • Yasiru Nayanajith
    Yasiru Nayanajith about 4 years
    Depreciated in API 27