问题:ViewPager中的Fragment onResume()在片段实际可见之前被激发。

例如,我有2个带有ViewPager和FragmentPagerAdapter的片段。第二个片段仅对授权用户可用,我需要在片段可见时要求用户登录(使用警告对话框)。

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

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

如何做到这一点?


当前回答

下面是使用onPageChangeListener的另一种方法:

  ViewPager pager = (ViewPager) findByViewId(R.id.viewpager);
  FragmentPagerAdapter adapter = new FragmentPageAdapter(getFragmentManager);
  pager.setAdapter(adapter);
  pager.setOnPageChangeListener(new OnPageChangeListener() {

  public void onPageSelected(int pageNumber) {
    // Just define a callback method in your fragment and call it like this! 
    adapter.getItem(pageNumber).imVisible();

  }

  public void onPageScrolled(int arg0, float arg1, int arg2) {
    // TODO Auto-generated method stub

  }

  public void onPageScrollStateChanged(int arg0) {
    // TODO Auto-generated method stub

  }
});

其他回答

在版本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构造函数现在已被弃用。

我也有同样的问题。ViewPager执行其他片段生命周期事件,我无法更改该行为。我使用片段和可用的动画编写了一个简单的寻呼机。简单寻呼机

我重写了关联的FragmentStatePagerAdapter的Count方法,并让它返回总计数减去要隐藏的页数:

 public class MyAdapter : Android.Support.V13.App.FragmentStatePagerAdapter
 {   
     private List<Fragment> _fragments;

     public int TrimmedPages { get; set; }

     public MyAdapter(Android.App.FragmentManager fm) : base(fm) { }

     public MyAdapter(Android.App.FragmentManager fm, List<Android.App.Fragment> fragments) : base(fm)
     {
         _fragments = fragments;

         TrimmedPages = 0;
     }

     public override int Count
     {
         //get { return _fragments.Count; }
         get { return _fragments.Count - TrimmedPages; }
     }
 }

因此,如果最初有3个片段添加到ViewPager中,并且在满足某些条件之前只应显示前2个片段,则通过将TrimmerdPages设置为1来覆盖页面计数,并且它应只显示前两个页面。

这对结尾的页面很有用,但对开头或中间的页面没有帮助(尽管有很多方法)。

注意,在活动/片段停止时不会调用setUserVisibleHint(false)。您仍然需要检查启动/停止以正确注册/注销任何侦听器等。

此外,如果片段以不可见状态开始,则会得到setUserVisibleHint(false);您不想在那里注销,因为在这种情况下,您以前从未注册过。

@Override
public void onStart() {
    super.onStart();

    if (getUserVisibleHint()) {
        // register
    }
}

@Override
public void onStop() {
    if (getUserVisibleHint()) {
        // unregister
    }

    super.onStop();
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if (isVisibleToUser && isResumed()) {
        // register

        if (!mHasBeenVisible) {
            mHasBeenVisible = true;
        }
    } else if (mHasBeenVisible){
        // unregister
    }
}

kris larson在这里发布的另一个替代pageradapter中setPrimaryItem的解决方案几乎对我有效。此外,我还从片段中的视图等获得了NPE,因为在最初几次调用此方法时,还没有准备好。通过以下更改,这对我有效:

private int mCurrentPosition = -1;

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
    super.setPrimaryItem(container, position, object);

    if (position == mCurrentPosition) {
        return;
    }

    if (object instanceof MyWhizBangFragment) {
        MyWhizBangFragment fragment = (MyWhizBangFragment) object;

        if (fragment.isResumed()) {
            mCurrentPosition = position;
            fragment.doTheThingYouNeedToDoOnBecomingVisible();
        }
    }
}