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

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

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

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

如何做到这一点?


当前回答

一种简单的实现方法是在进入片段之前检查用户是否已登录。

在MainActivity中,您可以在onNavigationItemSelected方法中执行类似的操作。

 case R.id.nav_profile_side:


                if (User_is_logged_in) {

                    fragmentManager.beginTransaction()
                            .replace(R.id.content_frame
                                    , new FragmentProfile())
                            .commit();
                }else {

                    ShowLoginOrRegisterDialog(fragmentManager);

                }

                break;

然而,如果您使用的是导航抽屉,尽管我们没有转到ProfileFragment,但抽屉中的选择将更改为Profile。

要将选择重置为当前选择,请运行以下代码

        navigationView.getMenu().getItem(0).setChecked(true);

其他回答

我重写了关联的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来覆盖页面计数,并且它应只显示前两个页面。

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

package com.example.com.ui.fragment;


import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.com.R;

public class SubscribeFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_subscribe, container, false);
        return view;
    }

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

        if (isVisibleToUser) {
            // called here
        }
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }
}

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

我们有一个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);
}

我发现只有在片段真正可见的情况下才调用onCreateOptionsMenu和onPrepareOptionsMenus方法。我找不到任何这样的方法,我也尝试了OnPageChangeListener,但它不适用于这种情况,例如,我需要在onCreate方法中初始化一个变量。

因此,这两种方法可以作为解决此问题的变通方法,特别适用于小而短的工作。

我认为,这是更好的解决方案,但不是最好的。我会使用这个,但同时等待更好的解决方案。

当做