方向更改后,Android片段反向堆栈动画失败

时间:2015-05-07 17:10:08

标签: android animation android-fragments android-orientation fragment-backstack

我有一个活动,它主持两个片段,一次只显示一个片段。有效地,用户可以通过不同的环境条件在任何给定时间在两者之间切换。

LoginFragment这是用户登录时看到的第一件事,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. 导航回登录片段
  5. 登录片段现在存在但不可见 - 好像从未播放popEnter动画一样。我知道它存在,因为我仍然可以与它互动。

    值得注意的还有以下几点:

    • 我在 片段
    • setRetainInstance(true)
    • 当用户从锁定片段重新定位设备时,会发生此
    • 我在模拟器和运行Lollipop的设备上尝试了相同的结果

    重新定位后后堆栈是否可能被损坏?

    谢谢!

1 个答案:

答案 0 :(得分:0)

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

  

控制是否在活动重新创建(例如从配置更改)中保留片段实例。这可以仅用于不在后栈中的片段。 [强调我的]

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