How to determine when Fragment becomes visible in

2018-12-31 03:47发布

Problem: Fragment onResume() in ViewPager is fired before the fragment becomes actually visible.

For example, I have 2 fragments with ViewPager and FragmentPagerAdapter. The second fragment is only available for authorized users and I need to ask the user to log in when the fragment becomes visible (using an alert dialog).

BUT the ViewPager creates the second fragment when the first is visible in order to cache the second fragment and makes it visible when the user starts swiping.

So the onResume() event is fired in the second fragment long before it becomes visible. That's why I'm trying to find an event which fires when the second fragment becomes visible to show a dialog at the appropriate moment.

How can this be done?

21条回答
泛滥B
2楼-- · 2018-12-31 04:07

Override setPrimaryItem() in the FragmentPagerAdapter subclass. I use this method, and it works well.

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
    // This is what calls setMenuVisibility() on the fragments
    super.setPrimaryItem(container, position, object);

    if (object instanceof MyWhizBangFragment) {
        MyWhizBangFragment fragment = (MyWhizBangFragment) object;
        fragment.doTheThingYouNeedToDoOnBecomingVisible();
    }
}
查看更多
残风、尘缘若梦
3楼-- · 2018-12-31 04:07

I encountered the same problem while working with FragmentStatePagerAdapters and 3 tabs. I had to show a Dilaog whenever the 1st tab was clicked and hide it on clicking other tabs.

Overriding setUserVisibleHint() alone didn't help to find the current visible fragment.

When clicking from 3rd tab -----> 1st tab. It triggered twice for 2nd fragment and for 1st fragment. I combined it with isResumed() method.

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

    // Make sure that fragment is currently visible
    if (!isVisible && isResumed()) {
        // Call code when Fragment not visible
    } else if (isVisible && isResumed()) {
       // Call code when Fragment becomes visible.
    }

}
查看更多
冷夜・残月
4楼-- · 2018-12-31 04:08

To detect Fragment in ViewPager visible, I quite sure that only using setUserVisibleHint is not enough.
Here is my solution for check fragment visible, invisible when first launch viewpager, switch between page, go to another activity/fragment/ background/foreground`

public class BaseFragmentHelpLoadDataWhenVisible extends Fragment {
    protected boolean mIsVisibleToUser; // you can see this variable may absolutely <=> getUserVisibleHint() but it not. Currently, after many test I find that

    /**
     * This method will call when viewpager create fragment and when we go to this fragment from
     * background or another activity, fragment
     * NOT call when we switch between each page in ViewPager
     */
    @Override
    public void onStart() {
        super.onStart();
        if (mIsVisibleToUser) {
            onVisible();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mIsVisibleToUser) {
            onInVisible();
        }
    }

    /**
     * This method will call at first time viewpager created and when we switch between each page
     * NOT called when we go to background or another activity (fragment) when we go back
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        mIsVisibleToUser = isVisibleToUser;
        if (isResumed()) { // fragment have created
            if (mIsVisibleToUser) {
                onVisible();
            } else {
                onInVisible();
            }
        }
    }

    public void onVisible() {
        Toast.makeText(getActivity(), TAG + "visible", Toast.LENGTH_SHORT).show();
    }

    public void onInVisible() {
        Toast.makeText(getActivity(), TAG + "invisible", Toast.LENGTH_SHORT).show();
    }
}

EXPLANATION You can check the logcat below carefully then I think you may know why this solution will work

First launch

Fragment1: setUserVisibleHint: isVisibleToUser=false isResumed=false
Fragment2: setUserVisibleHint: isVisibleToUser=false isResumed=false
Fragment3: setUserVisibleHint: isVisibleToUser=false isResumed=false
Fragment1: setUserVisibleHint: isVisibleToUser=true isResumed=false // AT THIS TIME isVisibleToUser=true but fragment still not created. If you do something with View here, you will receive exception
Fragment1: onCreateView
Fragment1: onStart mIsVisibleToUser=true
Fragment2: onCreateView
Fragment3: onCreateView
Fragment2: onStart mIsVisibleToUser=false
Fragment3: onStart mIsVisibleToUser=false

Go to page2

Fragment1: setUserVisibleHint: isVisibleToUser=false isResumed=true
Fragment2: setUserVisibleHint: isVisibleToUser=true isResumed=true

Go to page3

Fragment2: setUserVisibleHint: isVisibleToUser=false isResumed=true
Fragment3: setUserVisibleHint: isVisibleToUser=true isResumed=true

Go to background:

Fragment1: onStop mIsVisibleToUser=false
Fragment2: onStop mIsVisibleToUser=false
Fragment3: onStop mIsVisibleToUser=true

Go to foreground

Fragment1: onStart mIsVisibleToUser=false
Fragment2: onStart mIsVisibleToUser=false
Fragment3: onStart mIsVisibleToUser=true

DEMO project here

Hope it help

查看更多
ら面具成の殇う
5楼-- · 2018-12-31 04:08

I used this and it worked !

mContext.getWindow().getDecorView().isShown() //boolean
查看更多
不流泪的眼
6楼-- · 2018-12-31 04:09

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 {
        }
    }
}
查看更多
泛滥B
7楼-- · 2018-12-31 04:09

Here is another way using onPageChangeListener:

  ViewPager pager = (ViewPager) findByViewId(R.id.viewpager);
  FragmentPagerAdapter adapter = new FragmentPageAdapter(getFragmentManager);
  pager.setAdapter(adapter);
  pager.setOnPageChangeListener(new OnPageChangeListener() {

  public void onPageSelected(int pageNumber) {
    // Just define a callback method in your fragment and call it like this! 
    adapter.getItem(pageNumber).imVisible();

  }

  public void onPageScrolled(int arg0, float arg1, int arg2) {
    // TODO Auto-generated method stub

  }

  public void onPageScrollStateChanged(int arg0) {
    // TODO Auto-generated method stub

  }
});
查看更多
登录 后发表回答