问题:ViewPager中的Fragment onResume()在片段实际可见之前被激发。
例如,我有2个带有ViewPager和FragmentPagerAdapter的片段。第二个片段仅对授权用户可用,我需要在片段可见时要求用户登录(使用警告对话框)。
但是,当第一个片段可见时,ViewPager创建第二个片段,以便缓存第二个碎片,并在用户开始滑动时使其可见。
因此,onResume()事件在第二个片段可见之前很久就被激发了。这就是为什么我试图找到一个事件,当第二个片段变得可见时,该事件会触发,以便在适当的时候显示对话框。
如何做到这一点?
更新: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中只有一个片段可以将其菜单项与父活动的项放在一起。
我们有一个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);
}
在版本androidx.fragment:frage:1.1.0的ViewPager2和ViewPager中,您可以使用onPause和onResume回调来确定用户当前可见的片段。当片段可见时调用onResume回调,当片段停止可见时调用onPause回调。
在ViewPager2的情况下,这是默认行为,但同样的行为可以很容易地为旧的好ViewPager启用。
要在第一个ViewPager中启用此行为,必须将FragmentPagerAdapter.behavior_RESUME_ONLY_CURRENT_FRAGMENT参数作为FragmentPagerAdapter构造函数的第二个参数传递。
FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
注意:在android jetpack的新版本Fragment中,setUserVisibleHint()方法和带有一个参数的FragmentPagerAdapter构造函数现在已被弃用。
重写FragmentPagerAdapter子类中的setPrimaryItem()。我用这个方法,而且效果很好。
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
// This is what calls setMenuVisibility() on the fragments
super.setPrimaryItem(container, position, object);
if (object instanceof MyWhizBangFragment) {
MyWhizBangFragment fragment = (MyWhizBangFragment) object;
fragment.doTheThingYouNeedToDoOnBecomingVisible();
}
}