协慌网

登录 贡献 社区

如何确定片段何时在 ViewPager 中可见

问题:在片段实际可见之前,已触发ViewPager片段onResume()

例如,我有 2 个带有ViewPagerFragmentPagerAdapter 。第二个片段仅适用于授权用户,我需要让用户在该片段可见时登录(使用警报对话框)。

但是,当第一个片段可见时, ViewPager会创建第二个片段,以便缓存第二个片段,并在用户开始滑动时使其可见。

因此, onResume()事件在它可见之前就在第二个片段中触发了。这就是为什么我试图找到一个事件,该事件在第二个片段变得可见时触发,并在适当的时候显示一个对话框。

如何才能做到这一点?

答案

如何确定片段何时在 ViewPager 中可见

你可以通过覆盖以下setUserVisibleHint在你的Fragment

public class MyFragment extends Fragment {
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
        }
        else {
        }
    }
}

更新 :Android 支持库(rev 11)最终修复了用户可见的提示问题 ,现在,如果您将支持库用于片段,则可以安全地使用getUserVisibleHint()或覆盖setUserVisibleHint()来捕获更改(如戈恩的回答所述)。

更新 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 Support Library pre-r11中使用FragmentStatePagerAdapter ,则预缓存的片段也会置于 “可见” 状态(实际上是不可见)。

我覆盖:

public class MyFragment extends Fragment {
    @Override
    public void setMenuVisibility(final boolean visible) {
        super.setMenuVisibility(visible);
        if (visible) {
            // ...
        }
    }
   // ...
}

要捕获片段的焦点状态,我认为这是 “可见性” 的最合适状态,因为 ViewPager 中只有一个片段实际上可以将其菜单项与父活动项一起放置。

这似乎可以恢复您期望的正常onResume()行为。按下 Home 键离开应用程序,然后重新进入应用程序,可以很好地发挥作用。 onResume()不能连续调用两次。

@Override
public void setUserVisibleHint(boolean visible)
{
    super.setUserVisibleHint(visible);
    if (visible && isResumed())
    {
        //Only manually call onResume if fragment is already visible
        //Otherwise allow natural fragment lifecycle to call onResume
        onResume();
    }
}

@Override
public void onResume()
{
    super.onResume();
    if (!getUserVisibleHint())
    {
        return;
    }

    //INSERT CUSTOM CODE HERE
}