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

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

以下片段将解释我的问题。

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"); } ... }); } 

在这里,我可以跟踪在我的应用程序内的任何活动出现在屏幕上。 有什么方法可以在碎片上扩展这种方法吗?

就像Activity.getFragmentManager().registerFragmentLifecycleCallbacks();

UPD。 我对活动实现一无所知,他们是否全部使用片段,以及他们如何使用它们(通过xml,ViewPager注入等)。我的类中唯一的一个是应用程序上下文。 我们假设活动和片段实现是黑盒子,我不能做任何改变。

如果没有触及Activity或Fragment代码,并且假设您不知道它所在的标签或布局,那么您可以做的事情很less。 我可以看到最好的是,你可以在ActivityResumed和ActivityStoppedcallback中获得FragmentManager(因为这里有一个Activity引用)并应用BackstackChangedListener。 这假设您在片段之间切换时使用了堆栈。

您所要求的问题是,如果您不能控制中间人,那么已经缺lessFragmentcallback的活动,则您希望在应用程序级别上使用Fragments的生命周期callback。 他们通过他们的FragmentManager完成大部分的事情,并且将他们自己的生命周期callback传递给碎片,这样碎片就可以正常工作。 片段中的onResume和onPausecallback仅在首次创build或Activity遇到这些callback时发生。 活动中的片段只有一个生命周期callback,onAttachFragment,如果您可以覆盖,则会给您提供附加到活动的片段的引用。 但是你说你不能改变活动或片段,而且你想知道什么时候显示片段。

所以如果你不使用backstack,我不认为有办法做你想要的。

在你的片段中,重写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"); } } 

希望为你工作!

为了将Fragments SlidingTabLayout活动中,我使用Google使用的SlidingTabLayout 。 在它里面你有ViewPager和一些Adapter来填充许多碎片。 首先你必须把这个和这个文件放到你的项目中。 那么这里有一个很好的教程,你可以如何实现SlidingTabLayout

1)在Activity中实现了SlidingTabLayout之后,您可以从Activity中检测何时以及哪个Fragment可见:

  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)你可以检测片段是否从片段本身可见,因为我在这里回答,但是这可能会在片段的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); } }); 

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

尝试这个

  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(); } 

你可以通过内置的方法“onActivityCreated(Bundle)”知道下面这个方法,告诉你已经创build了这个片段,这样你就可以知道这个片断出现在屏幕上了。

我已经查看了什么是可用的,而不使用基本的FragmentActivity类,但找不到任何。 我做了一个实现,为应用程序中的所有片段提供基本的(onAdded / onRemoved)function。 当然可以扩展它来报告片段的当前状态(onAttach,onResume,onPause,onDetach,…)。

你可以在这里find代码和示例: https : //github.com/Nillerr/FragmentLifecycleCallbacks

它适用于不支持库碎片和通过不同的实现支持库碎片。 支持库类使用更安全,应该更好地执行,因为不支持使用Reflection来访问片段,而支持库FragmentManager包含getFragments()方法。

如果你正在为你的视图设置一个片段,你可能会有一个容器将显示。 假设这个容器是一个名为R.id.container的FrameLayout,你可以这样做:

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

使用与活动相同的方式

在应用程序类中设置标志来检查片段的可见性,在片段中使用下面的代码

  @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(); 

这个界面是否提供了对你有帮助的东西?

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

这听起来像是最好的select,如果你不能覆盖片段自己的onResume()方法是创build自己的接口,扩展ActivityLifecycleCallbacks,然后把你的日志代码放在onFragmentResumed(Fragment yourFragment)方法。

你可以通过做这样的事情得到一个指向Fragment的指针:

 int yourFragmentId = 0; //assign your fragment's ID to this variable; Fragment yourFragment.getId(); FragmentManager fm = activity.getFragmentManager(); Fragment f = fm.findFragmentById(yourFragmentId); 

无论你想检查片段是否可见,只要检查isMenuVisible()值。 这是片段的方法,我用来检查可见片段,当我必须从viewpagerselect项目发射一些http请求。 希望这可以帮助。

在我的情况下,我在onActivityCreated()中使用此方法。

在你片段覆盖方法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 !!! } } 

不存在默认的方式,但你可以做自己的callback,我做了这个,工作正常,首先需要一个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); }} 

在'MyApp'类实现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; }} 

希望这可以帮助!