1

我有一个活动,它承载两个片段,一次只显示一个。实际上,通过不同的环境条件,用户应该能够在任何给定时间在两者之间切换。

有一个LoginFragmentwhich 是用户在登录时看到的第一件事,并且在用户登录并且我们看到他们的帐户被锁定(自然)之后LockoutFragment可能会替换它。LoginFragment

这是典型的情况,但是有一种情况LockoutFragment是首先呈现的,如果说,用户正在使用应用程序并且他们的帐户由于某种原因被锁定,我们重新打开主机活动(LoginActivity),显示LockoutFragment, 但是给他们一个“返回登录”按钮,它可以切换LoginFragment(也很自然)的外观。

因此,我的目标是允许用户在两​​个片段之间切换,以先显示的为准。我的宿主活动使用以下函数来实现这个效果:

private void showLockoutFragment() {
    if (mLockoutFragment == null) {
        mLockoutFragment = new LockoutFragment();
    }

    transitionToFragment(FRAGMENT_LOCKOUT, mLockoutFragment);
}

private void showLoginFragment() {
    if (mLoginFragment == null) {
        mLoginFragment = new LoginFragment();
    }

    transitionToFragment(FRAGMENT_LOGIN, mLoginFragment);
}

private void transitionToFragment(String transactionTag, Fragment fragment) {
    if (!getFragmentManager().popBackStackImmediate(transactionTag, 0)) {
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.setCustomAnimations(
                R.animator.fade_in, R.animator.fade_out,
                R.animator.fade_in, R.animator.fade_out);
        ft.addToBackStack(transactionTag);
        ft.replace(R.id.fragment_container, fragment, transactionTag);
        ft.commit();
    }
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // non configuration change launch
    if (savedInstanceState == null) {
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            // decide which fragment to show
            boolean shouldLockout = extras.getBoolean(EXTRA_SHOULD_LOCKOUT);
            if (shouldLockout) {
                showLockoutFragment();
            } else {
                showLoginFragment();
            }
        } else {
            showLoginFragment();
        }
    } else {
        // retrieve any pre-existing fragments
        mLoginFragment = (LoginFragment)getFragmentManager().findFragmentByTag(FRAGMENT_LOGIN);
        mLockoutFragment = (LockoutFragment)getFragmentManager().findFragmentByTag(FRAGMENT_LOCKOUT);
    }
}

这些功能像魅力一样协同工作,但有一个例外:当应用程序首次启动后,用户

  1. 尝试登录,
  2. 被带到锁定片段,
  3. 重新定向设备,并且
  4. 导航回登录片段,

登录片段现在存在但不可见- 好像popEnter动画从未播放过。我知道它存在,因为我仍然可以与它互动。

还值得注意的是:

  • setRetainInstance(true)两个片段
  • 在用户从锁定片段重新定向设备时发生
  • 我在模拟器和运行 Lollipop 的设备上都试过这个,结果相同

重新定向后后堆栈是否可能被破坏?

谢谢!

4

1 回答 1

0

好的,事实证明问题实际上在于我对setRetainInstance. 根据该方法的文档:

控制是否在 Activity 重新创建期间(例如从配置更改)保留片段实例。这只能与不在后台堆栈中的片段一起使用。[强调我的]

虽然这对我来说似乎相当神秘,但似乎setRetainInstance(true)在后堆栈上的片段上使用可能只会产生意想不到的后果。在我的例子中,片段似乎被保留了,但它的popEnter动画从未被调用(旋转后)。再一次,很奇怪,但我想只是避免这种组合。

于 2015-05-12T04:52:18.253 回答