2015-04-06 98 views
9

我的代码的某些部分如何知道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实现是黑盒子,我无法做出任何更改。

+0

如果您的Fragment的onResume方法被调用,那意味着您的片段对用户可见。 – Toppers 2015-04-06 11:36:28

+0

好吧...比方说,片段实现是一个黑盒子,我没有能力添加几行代码。 – 2015-04-06 12:57:39

+0

因此,您推动反应迟钝的应用程序设计。 – danny117 2015-04-14 16:31:07

回答

0

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

+0

请看看我的问题的UPD部分。 – 2015-04-06 13:19:58

+0

我相信唯一可靠的机制是依赖活动的onWindowFocusChanged()方法,从而通过您创建的接口公开此事件。但是,您仍然需要将界面与活动本身连接起来。 – 2015-04-06 13:30:22

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

不幸的是,我对片段事务中使用的标签或标识一无所知。我看起来像“片段生命周期观察员”。据我深入研究这个问题 - 我什么都没发现。无论如何,这并不意味着解决方案不存在:) – 2015-04-07 05:46:58

0

可以知道与内置的名为“onActivityCreated(包)”方法,下面这个方法告诉该片段已这样创造了你得知片段出现在屏幕上Click here for reference 希望它有帮助

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

希望这项工作为您服务!

+0

它的工作原理。很棒 – 2017-08-23 23:07:01

0

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

您可以在这里一个样品一起找到代码:https://github.com/Nillerr/FragmentLifecycleCallbacks

它可以工作在通过不同的实现不支持文库片段和支持库片段。支持库类使用更安全,应该执行得更好,因为不支持使用Reflection来访问片段,而支持库FragmentManager包含getFragments()方法。

0

如果您正在为您的视图设置片段,那么您可能有一个容器将显示它。假设这个容器是一个Frame.Rayout,其ID为R.id.容器,你可以这样做:

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

使用相同的方式,活动

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

​​

与片段沟通使用下面的代码您必须将该活动添加到哪个片段中,然后使用以下代码

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

不幸的是,我无法对碎片进行任何修改:(另外我知道它们存在的任何内容,它们的名称,事务标签等等......目前唯一的解决方案是创建一堆' TrackableFragment'类,并强制开发人员扩展它们,这是最直接明了的方式,但不是最优雅的方式。 – 2015-04-15 12:15:31

5

如果没有触及Activity或Fragment代码,并且假设您不知道它所在的标签或布局,那么您可以执行的操作很少。我可以看到的最好的结果是,您可以在ActivityResumed和ActivityStopped回调中获取FragmentManager(因为这里有一个Activity引用)并应用BackstackChangedListener。这假设你在片段之间改变时使用了backstack。

问题与你要求的是,当你无法控制中间人时,你需要在应用程序级别上对碎片进行生命周期回调,而这些中间人已经缺乏Fragment回调。他们通过他们的FragmentManager完成大部分任务,并将他们自己的生命周期回调传播到碎片中,这样碎片就可以正常工作。片段中的onResume和onPause回调仅在第一次创建或Activity遇到这些回调时发生。活动中的片段只有一个生命周期回调,onAttachFragment,如果您可以覆盖,则会为您提供附加到活动的片段的引用。但是你说你不能改变活动或片段,并且你想知道片段何时显示。

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

+0

恐怕是这样。悲伤但是真实的,直到我找到解决方案) – 2015-04-16 19:44:57

0

此接口是否提供对您有用的任何东西?

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

这听起来像你最好的选择,如果你不能覆盖片段自身onResume()的方法是创建你自己的界面,扩展ActivityLifecycleCallbacks,然后把你的日志代码在onFragmentResumed(Fragment yourFragment)方法。

你可以做这样的事情得到一个指针片段:

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

为了把片段内的活动我使用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); 
     } 

    }); 
0

徘徊无论ü要检查是否片段可见或不..只是检查isMenuVisible()值。 这是片段的方法,我用来检查可见的片段,当我必须从viewpager选择的项目发射一些http请求。 希望这有助于。

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

+1

'isMenuVisible()'至少从v25开始是私人的(@hide)。 – ypresto 2017-04-04 10:17:15

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 !!! 
    } 

} 
0

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

希望这有助于!

相关问题