现在对于android app而言,fragment的使用已经非常广泛。大概分为两种情况:第一种是直接使用Activity装载fragment,第二种是ViewPager+Fragment,所以fragment的切换就变成了很频繁的操作。fragment的切换又分两种情况:
- 每次创建新的实例进行替换
- 先创建好,每次通过 show()或者hide() 方法控制显示隐藏
不管上述哪种情况,我们在大多数情况下,都需要知道具体哪个fragment显示在用户面前或者第一次显示在用户面前这样一个时机,好让用户看到我们想展示给他的数据。下面给出两种对应的解决方案,仅供参考:
一,通过Activity直接装载多个Fragment(多用于最外层导航tab页)
主要方式:通过重写onHiddenChanged(boolean hidden)方法
这个方法是V4包中Fragment的方法,当Fragment对用户可见性改变的时候,这个方法会被调用。参数 hidden 的值 为false 表示 可见, true表示不可见。要注意的是,但Fragment第一次被add到Activity的时候,这个方法不会被调用。所以要处理一下fragment 第一次对用户可见的情况。
先写一个BaseFragment ,让所有的fragment继承自它。
public class BaseFragment extends Fragment {
protected boolean isFirstVisible = false;
public BaseFragment() {
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
isFirstVisible = true;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public void onStart() {
super.onStart();
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onPause() {
super.onPause();
isFirstVisible = false;
}
@Override
public void onStop() {
super.onStop();
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onDetach() {
super.onDetach();
}
}
主要是在BaseFragment里面定义了一个boolean类型的变量。用来表示是否是第一次可见。让所有fragment也能继承这个属性。接下来去看具体的Fragment代码:
public class FindFragment extends BaseFragment {
private static final String TAG = "FindFragment";
@Override
public void onResume() {
super.onResume();
Log.d("xls", "FindFragment onResume");
if(isFirstVisible){
LogUtil.d("xiong","FindFragment 第一次可见");
}
}
@Override
public void onHiddenChanged(boolean hidden) {
Log.d("xls", "FindFragment onHiddenChanged : " + hidden);
if (hidden) {
//隐藏
isFirstVisible = false;
} else {
//显示
LogUtil.d("xiong","FindFragment 显示");
}
}
}
第一次可见在 onResume中,if语句里,后面就都是在onHiddenChanged方法里。
二,ViewPager+Fragment配合使用
主要方式:通过重写setUserVisibleHint方法。
同样的先写一个BaseFragment:
public class BaseFragment extends Fragment {
protected boolean isVisible;
public BaseFragment() {
// Required empty public constructor
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
isVisible = true;
onVisible();
}else{
isVisible = false;
onInVisible();
}
}
public void onVisible(){
}
public void onInVisible(){
}
}
BaseFrament里面增加了两个方法onVisible 和 onInVisible用于给子Fragment回调。当然这个位置可以根据自己的习惯去定义回调方式。
具体的子Fragment如下:
public class ProducingFragment extends BaseFragment {
public ProducingFragment() {
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onVisible() {
super.onVisible();
Log.d("xls", "producingFragment is Visible");
if (!isResumed()) {
return;
}
//do your work here
}
@Override
public void onInVisible() {
super.onInVisible();
Log.d("xls", "producingFragment is InVisible");
}
}
需要注意的是,setUserVisibleHint这个方法是被系统调用的,一般最早的一次是在fragment的onResume方法被调用之前,如果这个时候你的控件都没有初始化完成,就会出问题。所以在 onVisible方法里 加了一个判断,看这个Fragment是否已经Resume了,再去处理业务逻辑。
如果要做第一次显示判断,则跟第一种方式逻辑类似。
以上为个人的总结,欢迎各位同道点评。。。。