1

一度に 1 つだけが表示される 2 つのフラグメントをホストするアクティビティがあります。事実上、ユーザーは、さまざまな環境条件を通じて、いつでも 2 つの間を切り替えることができる必要があります。

ユーザーがLoginFragmentログイン時に最初に目にする と、ユーザーがログインして (自然に) アカウントがロックされLockoutFragmentた後に に置き換わる可能性のある があります。LoginFragment

それが典型的なケースなのですが、LockoutFragment例えばユーザーがアプリを使っていて何らかの理由でアカウントがロックされていて、ホストアクティビティ( LoginActivity)を再度開いてLockoutFragment、の外観を切り替える「ログインに戻る」ボタンを提供しますLoginFragment(これも当然です)。

したがって、私の目標は、ユーザーが 2 つのフラグメントのうち、最初に表示された方を切り替えられるようにすることです。ホスト アクティビティでは、次の関数を使用してこの効果を実現しています。

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。その方法のドキュメントによると:

アクティビティの再作成 (構成の変更など) の間、フラグメント インスタンスを保持するかどうかを制御します。これは、バック スタックにないフラグメントでのみ使用できます。[鉱山を強調]

これは私には不可解に見えsetRetainInstance(true)ますが、バックスタックにあるフラグメントを使用すると、意図しない結果が生じる可能性があるようです。私の場合、フラグメントは保持されているように見えましたが、そのpopEnterアニメーションは呼び出されませんでした (回転後)。繰り返しますが、奇妙ですが、その組み合わせは避けてください。

于 2015-05-12T04:52:18.253 に答える