问题:ViewPager中的Fragment onResume()在片段实际可见之前被激发。
例如,我有2个带有ViewPager和FragmentPagerAdapter的片段。第二个片段仅对授权用户可用,我需要在片段可见时要求用户登录(使用警告对话框)。
但是,当第一个片段可见时,ViewPager创建第二个片段,以便缓存第二个碎片,并在用户开始滑动时使其可见。
因此,onResume()事件在第二个片段可见之前很久就被激发了。这就是为什么我试图找到一个事件,当第二个片段变得可见时,该事件会触发,以便在适当的时候显示对话框。
如何做到这一点?
我们有一个MVP的特殊情况,其中片段需要通知演示者视图已可见,并且演示者由Dagger在fragment.onAttach()中注入。
setUserVisibleHint()还不够,我们检测到需要解决的3种不同情况(提到onAttach(),以便您知道演示者何时可用):
片段刚刚创建。系统进行以下调用:setUserVisibleHint()//在片段的生命周期调用之前,因此演示者为空onAttach()...打开恢复()片段已创建,并按下主页按钮。将应用程序恢复到前台时,这称为:打开恢复()方向更改:onAttach()//演示者可用打开恢复()setUserVisibleHint()
我们只希望可见性提示到达演示者一次,所以我们是这样做的:
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_list, container, false);
setHasOptionsMenu(true);
if (savedInstanceState != null) {
lastOrientation = savedInstanceState.getInt(STATE_LAST_ORIENTATION,
getResources().getConfiguration().orientation);
} else {
lastOrientation = getResources().getConfiguration().orientation;
}
return root;
}
@Override
public void onResume() {
super.onResume();
presenter.onResume();
int orientation = getResources().getConfiguration().orientation;
if (orientation == lastOrientation) {
if (getUserVisibleHint()) {
presenter.onViewBecomesVisible();
}
}
lastOrientation = orientation;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (presenter != null && isResumed() && isVisibleToUser) {
presenter.onViewBecomesVisible();
}
}
@Override public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(STATE_LAST_ORIENTATION, lastOrientation);
}
更新:Android支持库(rev 11)最终修复了用户可见提示问题,现在如果您将支持库用于片段,那么您可以安全地使用getUserVisibleHint()或重写setUserVisibleHint()来捕获gorn的答案所描述的更改。
UPDATE 1 getUserVisibleHint()有一个小问题。默认情况下,该值为true。
// Hint provided by the app that this fragment is currently visible to the user.
boolean mUserVisibleHint = true;
因此,在调用setUserVisibleHint()之前尝试使用它可能会出现问题。作为解决方法,您可以像这样在onCreate方法中设置值。
public void onCreate(@Nullable Bundle savedInstanceState) {
setUserVisibleHint(false);
过时的答案:
在大多数使用情况下,ViewPager一次只显示一个页面,但如果您在Android支持库r11之前的版本中使用FragmentStatePagerAdapter,则预缓存的片段也会处于“可见”状态(实际上不可见)。
我覆盖:
public class MyFragment extends Fragment {
@Override
public void setMenuVisibility(final boolean visible) {
super.setMenuVisibility(visible);
if (visible) {
// ...
}
}
// ...
}
为了捕获片段的焦点状态,我认为这是最适合的“可见性”状态,因为ViewPager中只有一个片段可以将其菜单项与父活动的项放在一起。
setUserVisibleHint(布尔可见)现在已弃用,因此这是正确的解决方案
FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
在版本androidx.fragment:frage:1.1.0的ViewPager2和ViewPager中,您可以使用onPause()和onResume()来确定用户当前可以看到哪个片段。当片段可见时调用onResume(),当片段停止可见时调用onPause()。
要在第一个ViewPager中启用此行为,必须将FragmentPagerAdapter.behavior_RESUME_ONLY_CURRENT_FRAGMENT参数作为FragmentPagerAdapter构造函数的第二个参数传递。
当视图寻呼机中的片段显示在屏幕上供用户查看时,我试图启动计时器时遇到了这个问题。
计时器总是在用户看到片段之前启动。这是因为片段中的onResume()方法在我们看到片段之前被调用。
我的解决方案是检查onResume()方法。当片段8是视图页面的当前片段时,我想调用某个方法“foo()”。
@Override
public void onResume() {
super.onResume();
if(viewPager.getCurrentItem() == 8){
foo();
//Your code here. Executed when fragment is seen by user.
}
}
希望这有帮助。我经常看到这个问题。这似乎是我见过的最简单的解决方案。其他很多都与较低的API等不兼容。