不同的情况
在Activity中直接使用
这种情况是最简单的,也就是在Activity使用XML引入,或者使用FragmentManager 的addFragment或者replaceFrament 动态载入。在这种情况下,只要监听Fragment的onResume和onPause方法就能够判断其显隐。在onResume和onPause中间是对用户可见的.
@Override
public void onResume() {
super.onResume();
//TODO now visible to user
}
@Override
public void onPause() {
super.onPause();
//TODO now invisible to user
}
使用show和hide来显隐的Fragment
FragmentManager除了addFragment和replaceFragment之外还有showFragment和hideFragment来做Fragment的显隐,这样可以提生页面切换的速度,是一种用空间换时间的方式。但是这样使用的Fragment在被hide的时候是不会调用onPause方法的。因为它只是在屏幕中不可见了,但是没有Pause。这时候我们需要监听onHiddenChanged方法
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if(hidden){
//TODO now visible to user
} else {
//TODO now invisible to user
}
}
但是我们需要注意一点,那就是,如果用户直接按home键退出了,我们的程序也没有对按home键事件进行监听,在按home键时调用hideFragment,那么onHiddenChanged事实上没有被调用,反而是onPause被调用了。所以我们需要针对这样的情况做特殊的处理。比如在home键退出时显示调用一下hideFragment或者在onPause中也发信号说本Fragment不可见了,这都是可以的。
在ViewPager中的Fragment
现在安卓市场上基本上的app都会做tab页,而tab页基本都是通过android自带的ViewPager实现的。ViewPager有这样一个特点,当滑到某一个Tab时,它会同时加载这个tab的左右两个tab页,比如我从1页面切换到了2页面,那么3页面的onResume也被调用了,但是3页面其实对用户是不可见的。这时候我们就需要监听setUserVisibleHint来判断到底对用户是否可见。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
//TODO now it's visible to user
} else {
//TODO now it's invisible to user
}
}
但是与第二条类似,我们依然不能完全依赖setUserVisibleHint这个方法来判断是否ViewPager中的页面是否对用户可见。因为该方法只有在Fragment切换的时候被调用。比如我从一个含有ViewPager的Actvity跳转到另一个activity,ViewPager中的Fragment的 setUserVisibleHint方法是不会被调用的,只能通过onPause来判断。进入该Activity原理类似。那么怎么办呢,我们需要结合setUserVisibleHint和onResume和onPause。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if ((isVisibleToUser && isResumed())) {
onResume();
} else if (!isVisibleToUser) {
Timber.i("On Pause on %s Fragment Invisble", getClass().getSimpleName());
onPause()
}
}
@Override
public void onResume() {
super.onResume();
if (getUserVisibleHint()) {
Timber.i("On Resume on %s Fragment Visible", getClass().getSimpleName());
//TODO give the signal that the fragment is visible
}
}
@Override
public void onPause() {
super.onPause();
//TODO give the signal that the fragment is invisible
}
判断Fragment是否对用户可见的方法是通过setUserVisibleHint来实现的。
1、通过重写setUserVisibleHint来动态设定Fragment是否可见
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
isVisible = isVisibleToUser;
// Make sure that fragment is currently visible
if (!isVisible && isResumed()) {
// 调用Fragment隐藏的代码段
} else if (isVisible && isResumed()) {
// 调用Fragment显示的代码段
}
}
2、setUserVisibleHint这个方法默认是true,确实是需要用户手动调用的,如果你使用fragment配合FragmentPagerAdapter使用的话,adapter会在内部控制setUserVisibleHintFragment() 这个方法(请看FragmentPagerAdapter源码) ,如果是自己控制fragment的话,就需要手动调用setUserVisibleHintFragment() 这个方法了。