如何检测片段何时出现在屏幕上?

时间:2015-04-06 10:57:10

标签: android android-fragments

我的代码的某些部分如何知道片段实例在屏幕上变得可见?

以下代码段将解释我的问题。

public class MyApp extends Application {
public static final String TAG = MyApp.class.getSimpleName();

@Override
public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
        ...

        @Override
        public void onActivityResumed(Activity activity) {
           Log.d(TAG, activity.getClass().getSimpleName() + " is on screen");
        }

        @Override
        public void onActivityStopped(Activity activity) {
            Log.d(TAG, activity.getClass().getSimpleName() + " is NOT on screen");
        }

        ...
    });
}

在这里,我可以跟踪我的应用中的任何活动何时出现在屏幕上。有没有办法在Fragments上扩展这种方法?

喜欢的东西 Activity.getFragmentManager().registerFragmentLifecycleCallbacks();

UPD。我对活动实现一无所知,他们是否使用片段以及如何使用它们(通过xml,ViewPager等注入)我班上唯一的东西是应用背景。我们假设Activity和Fragment实现是黑盒子,我无法进行任何更改。

14 个答案:

答案 0 :(得分:5)

在您的片段中,覆盖onHiddenChanged(...)方法:

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (hidden) {
        Log.d(TAG, ((Object) this).getClass().getSimpleName() + " is NOT on screen");        
    } 
    else 
    {
        Log.d(TAG, ((Object) this).getClass().getSimpleName() + " is on screen");
    }
}

希望这对你有用!

答案 1 :(得分:5)

如果没有触及活动或片段代码,并且假设您不知道它所放置的标签或布局,那么您可以做的很少。我能看到的最好的是你可以在ActivityResumed和ActivityStopped回调中获取FragmentManager(因为这里有一个Activity引用)并应用BackstackChangedListener。这假设您在更改片段时使用了Backstack。

您要问的问题是,当您无法控制中间人,即已经缺乏Fragment回调的活动时,您希望在应用程序级别上对Fragments进行生命周期回调。它们通过FragmentManager完成大部分工作,并将自己的生命周期回调传播到Fragments,以便片段表现得恰当。片段中的onResume和onPause回调仅在首次创建时或者当Activity遇到这些回调时发生。 onAttachFragment中的Fragments只有一个生命周期回调函数,如果你可以覆盖它,它将为你提供对附加到Activity的Fragments的引用。但是你说你不能改变活动或片段,你想知道片段什么时候出现。

因此,如果您不使用背锯,我认为没有办法做您想做的事。

答案 2 :(得分:3)

要将片段放入Activity中,请使用Google使用的SlidingTabLayout。在其中,您有ViewPager和一些Adapter来填充许多碎片。首先,您必须在项目中放置thisthis个文件。然后here就如何实施SlidingTabLayout提供了很好的教程。

1)在您的活动中实施SlidingTabLayout后,您可以检测活动中何时以及哪些碎片可见:

  mSlidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
             //Do nothing
        }
        @Override
        public void onPageSelected(int position) {
            if (position == 0) {
                //Whenever first fragment is visible, do something
            } else if (position == 1) {
               //Whenever second fragment is visible, do something
            } else if (position == 2) {
               //Whenever third fragment is visible, do something
            } else if (position == 3) {
                //Whenever fourth fragment is visible, do something
            }
        }
        @Override
        public void onPageScrollStateChanged(int state) {
            //Do nothing
        }
    });

2)当我回答here时,您可以检测片段是否在片段中可见,但是这可能会在onCreateView()片段之前调用,因此请在链接:

@Override
public void setUserVisibleHint(boolean visible){
    super.setUserVisibleHint(visible);
    if (visible){
        //when this Fragment is active, do something
    }
}

3)您还可以在活动中更改每个标签的指标的颜色,如下所示:

    mSlidingTabLayout.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
        @Override
        public int getIndicatorColor(int position) {
            if (position == 0) {
                return getResources().getColor(R.color.orange);
            } else if (position == 1) {
                return getResources().getColor(R.color.redDimmed);
            } else if (position == 2) {
                return getResources().getColor(R.color.yellow);
            } else if (position == 3) {
                return getResources().getColor(R.color.green);
            } else {
                return getResources().getColor(R.color.redLight);
            }
        }

        @Override
        public int getDividerColor(int position) {
            return getResources().getColor(R.color.defaultActionBarBg);
        }

    });

答案 3 :(得分:1)

使用与活动相同的方式

在应用程序类中设置标志以检查片段的可见性,在片段

中使用下面的代码
    @Override
        public void onStart() {
            super.onStart();
           Log.e( "Fragment is visible", "Fragment is visible");
Application Class.isFragmentShow = true;
        }

    @Override
        public void onPause() {
            super.onPause();
            Log.e("Fragment is not visible", "Fragment is not visible");

Application Class.isFragmentShow = false;
        }

与片段进行通信,您必须调用添加了哪个片段的活动,然后使用下面的代码

MainFragment fragment = (MainFragment) fragmentManager.findFragmentByTag("MainFragment");
                    fragment.setFilter();

答案 4 :(得分:1)

不存在默认的方法,但你可以创建自己的Callbacks,我做了这个并且工作正常,首先需要一个BaseFragment类,我们将处理所有片段事件。

public class BaseFragment extends Fragment {

private String fragmentName;
private FragmentLifecycleCallbacks listener;

public void registerCallBacks(String fragmentName){
    // handle the listener that implement 'MyApp' class
try{
    listener = (FragmentLifecycleCallbacks) getActivity().getApplication();
   } catch (ClassCastException e) {
        throw new ClassCastException("Application class must implement FragmentLifecycleCallbacks");
    }
    // set the current fragment Name for the log
    this.fragmentName = fragmentName;
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    if(listener!=null) {
        listener.onAttachFragment(fragmentName);
    }
}

@Override
public void onResume() {
    super.onResume();
    if(listener!=null) {
        listener.onResumeFragment(fragmentName);
    }
}

@Override
public void onStop() {
    super.onStop();
    if(listener!=null) {
        listener.onStopFragment(fragmentName);
    }
}

// 'MyApp' class needs implement this interface to handle all the fragments events
public interface FragmentLifecycleCallbacks{
    void onStopFragment(String fragmentName);
    void onResumeFragment(String fragmentName);
    void onAttachFragment(String fragmentName);
}}

On' MyApp' class实现BaseFragment的接口

public class MyApp extends Application implements BaseFragment.FragmentLifecycleCallbacks{

public static final String TAG = MyApp.class.getSimpleName();

@Override
public void onCreate() {
    super.onCreate();
}


@Override
public void onStopFragment(String fragmentName) {
    Log.d(TAG, fragmentName + " is NOT on screen");
}

@Override
public void onResumeFragment(String fragmentName) {
    Log.d(TAG, fragmentName + " is on screen");
}

@Override
public void onAttachFragment(String fragmentName) {
    Log.d(TAG, fragmentName + " is attached to screen");
}}

现在你需要的每个片段都扩展了BaseFragment'并注册到全球监听者

public class FragmentA extends BaseFragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_simple, container, false);
    // here register to the global listener
    registerCallBacks(FragmentA.class.getName());

    return rootView;
}}

希望这有帮助!

答案 5 :(得分:0)

拦截活动中的onWindowFocusChanged()并将其传播给感兴趣的片段。

答案 6 :(得分:0)

试试这个

    private Boolean isFragmentVisible()
    {
      if(getFragmentManager().findFragmentByTag("TAG") != null && getFragmentManager().findFragmentByTag("TAG").isVisible())
      {
        //The fragment is visible
        return true;
      }
      return false;
    }

替代方式

    private Boolean isFragmentVisible()
    {
      return getFragmentManager().findFragmentByTag("TAG") != null && getFragmentManager().findFragmentByTag("TAG").isVisible();
    }

答案 7 :(得分:0)

您可以使用名为" onActivityCreated(Bundle)"的内置方法了解以下内容:此方法告诉已创建片段,因此您可以知道片段出现在屏幕上Click here for reference 希望它有所帮助

答案 8 :(得分:0)

我在不使用基础FragmentActivity类的情况下查看了可用内容,但找不到任何内容。我已经实现了为应用程序中的所有片段提供基本(onAdded / onRemoved)功能的实现。当然可以扩展它以报告片段的当前状态(onAttach,onResume,onPause,onDetach,...)。

您可以在此处找到代码和示例:https://github.com/Nillerr/FragmentLifecycleCallbacks

它适用于非支持库片段和通过不同实现支持库片段。支持库类使用起来更安全,并且性能更好,因为不支持库使用Reflection来访问片段,而支持库FragmentManager包含getFragments()方法。

答案 9 :(得分:0)

如果要将Fragment设置为View,则可能有一个容器可以显示它。假设这个容器是一个ID为R.id.container的FrameLayout,你可以这样做:

Fragment f = fragmentManager.findFragmentById(R.id.container);
if (f instanceof YourFragment) {
   // TODO something when YourFragment is ready
}

答案 10 :(得分:0)

此界面是否提供了对您有用的任何内容?

https://github.com/soarcn/AndroidLifecyle/blob/master/lifecycle/src/main/java/com/cocosw/lifecycle/FragmentLifecycleCallbacks.java

如果您无法覆盖Fragment自己的onResume()方法,那么您最好的选择是创建自己的扩展ActivityLifecycleCallbacks的接口,然后将您的日志记录代码放入{{1方法。

您可以通过执行以下操作来获取指向Fragment的指针:

onFragmentResumed(Fragment yourFragment)

答案 11 :(得分:0)

如果您想检查片段是否可见,请检查isMenuVisible()值。 这是片段的方法,当我必须从viewpager选择的项目中发出一些http请求时,我用它来检查可见片段。 希望这有帮助。

就我而言,我在onActivityCreated()中使用了这个方法。

答案 12 :(得分:0)

在片段覆盖方法中 setMenuVisibility 如果您正在使用ViewPager并从左右滑动,则在片段的可见性发生变化时会调用此方法。

以下是我项目中的示例

public abstract class DemosCommonFragment extends Fragment {

    protected boolean isVisible;

    public DemosCommonFragment() {
    }


    @Override
    public void setMenuVisibility(boolean menuVisible) {
        super.setMenuVisibility(menuVisible);
        isVisible = menuVisible;
        // !!! Do Something Here !!!
    }

}

答案 13 :(得分:0)

动画监听器

检查所有用例,但存在未处理的异常。您可以使用它来适应您的用例。请随时评论您的意见或它没有解决的用例。

注意:您可以通过处理 enter 中的 onCreateAnimation 来添加 fragmentWillDisappear 和 fragmentDidDisappear。

父片段:

public class BaseFragment extends Fragment {
    
    private Animation.AnimationListener animationListener;
    
    private void setAnimationListener(Animation.AnimationListener animationListener) {
        this.animationListener = animationListener;
    }
    
    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                fragmentWillAppear(animation);
            }
    
            @Override
            public void onAnimationEnd(Animation animation) {
                fragmentDidAppear(animation);
            }
    
            @Override
            public void onAnimationRepeat(Animation animation) {
        
            }
        });
    }
    
    @Override
    public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
        
        AnimationSet animSet = new AnimationSet(true);
        Animation anim = null;
        try {
            anim = AnimationUtils.loadAnimation(getActivity(), nextAnim);
        } catch (Exception error) {
            
        }
        
        if (anim != null) {
            anim.setAnimationListener(animationListener);
            animSet.addAnimation(anim);
        }
        
        return animSet;
    }
    
    public void fragmentDidAppear(Animation animation) {
        
    }
    
    public void fragmentWillAppear(Animation animation) {
    
    }
    
}

子片段:

class ChildFragment extends BaseFragment {
    
    @Override
    public void fragmentDidAppear(Animation animation) {
        super.fragmentDidAppear(animation);
    }
    
    @Override
    public void fragmentWillAppear(Animation animation) {
        super.fragmentWillAppear(animation);
    }
    
}