web-dev-qa-db-ja.com

FragmentTransaction:replaceとaddToBackStackが一緒に機能していませんか?

私はAndroid開発にかなり慣れておらず、今では奇妙な振る舞いに出くわしています。

  • フラグメントのコンテナとなる空のFrameLayoutがあります。
  • ユーザーが初めてボタンを押した場合は、新しいフラグメントを生成してコンテナー内に配置します。
  • ユーザーが後でボタンを押して、コンテナー内に既存のフラグメントがある場合は、既存のフラグメントを新しく生成されたフラグメントと置き換えます。
  • ユーザーが戻るボタンを押した場合は、コンテナー内のフラグメントをポップします。

これが私のコードです

public void showFragment(View v) {
    FragmentA f = new FragmentA();

    FragmentManager fm = getSupportFragmentManager();
    String tag = f.getFragmentTag(); // instance method of a to get a tag

    FragmentTransaction ft = fm.beginTransaction();
    ft.setCustomAnimations(R.anim.slide_in_top, 0, 0, R.anim.slide_out_top);            
    ft.replace(R.id.container, f, tag);
    ft.addToBackStack(tag);
    ft.commit();
}

@Override
public void onBackPressed() {
    FragmentManager fm = getSupportFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        fm.popBackStack();
    } else {
        super.onBackPressed();
    }
}

ユーザーが初めてボタンを押すと、期待どおりに動作し、コンテナーに新しいフラグメントを追加します。ただし、コンテナにフラグメントが含まれているときに2回目にボタンを押すと、置き換えるのではなく、既存のフラグメントの上に新しいフラグメントが追加されます。 つまり、コンテナ内に2つのフラグメントがあり、2回押してすべてのフラグメントを削除します。

行を削除すると、

ft.addToBackStack();

そして、次のようにonBackPress()メソッドを作り直します。これは、期待どおりに再び機能します(一度にコンテナー内に1つのフラグメント)

基本的に、popFromBackStackメソッドの代わりに手動でフラグメントを削除します

private FragmentA currentFragment = null; // to hold the reference to exising fragment, if any.

@Override
public void onBackPressed() {
    if (currentFragment != null) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.setCustomAnimations(0, R.anim.slide_out_top);
        ft.remove(currentFragment);
        ft.commit();

        currentFragment = null;
    } else {
        super.onBackPressed();
    }
}

だから、私の質問は

  • replaceとaddToBackStackが一緒に機能していませんか?
  • または、私は何か間違ったことをしましたか?

すべてのコメントと提案に感謝します。

9
Tar_Tw45

addToBackstackは、フラグメントの状態のスナップショットを作成します。つまり、戻るボタンを押すと、実際にはaddToBackstackが呼び出された最後の状態に戻ります。

あなたの場合、フラグメントを追加します。戻るボタンは、この追加されたフラグメントを削除します。 replaceを呼び出して、バックスタックに再度追加すると、バックスタックに2つの状態があります(1.最初のフラグメントを追加した場合、2。フラグメントを追加しなかった場合)。戻るボタンを押して現在のフラグメントを削除する場合は、addToBackstackを使用しないでください。ビュー内のフラグメントの状態を保持する場合にのみ、addToBackstackを使用してください。

14
Spidy