web-dev-qa-db-ja.com

戻るボタンが押されたときにフラグメントCをフラグメントAに置き換える方法

私のシナリオ:アクティビティ1はフラグメントA-> B-> Cで構成されています。すべてのフラグメントは次のコードを使用して追加されます。

_        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.content, fragment, TAG);
        ft.addToBackStack(TAG);
        ft.commit();
_

さて、フラグメントCから、フラグメントAに直接戻りたいと思っています。したがって、フラグメントCを追加するときにft.addToBackStack(TAG)をコメントしました。

ただし、フラグメントCはAに置き換えられません。実際、両方のフラグメントが表示されます。この問題を解決するにはどうすればよいですか?

34

理論

戻りたいポイントをマークするには、FragmentTransaction内から addToBackStack(tag:String):FragmentTransaction メソッドを使用します。 このメソッドは、チェーン機能のみのFragmentTransactionインスタンスを返します。

次に、FragmentManagerから popBackStackImmediate(tag:String,flag:int):void メソッドで戻ります。タグは前に指定したものです。フラグは、マークされたトランザクションを含む定数POP_BACK_STACK_INCLUSIVEまたは0です。

以下は、フラグメントがロードされるID content_frameを持つFrameLayoutを持つ次のレイアウトの例です。

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:paddingBottom="@dimen/activity_vertical_margin"
    Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

<TextView
    Android:id="@+id/textView"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="@string/hello_world" />

<FrameLayout
    Android:id="@+id/content_frame"
    Android:layout_below="@id/textView"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" />

</RelativeLayout>

以下のコードは、レイアウト要素のコンテンツをid content_frameに置き換えるときに、フラグメントクラス名でフラグメントをマークします。

public void loadFragment(final Fragment fragment) {

    // create a transaction for transition here
    final FragmentTransaction transaction = getSupportFragmentManager()
            .beginTransaction();

    // put the fragment in place
    transaction.replace(R.id.content_frame, fragment);

    // this is the part that will cause a fragment to be added to backstack,
    // this way we can return to it at any time using this tag
    transaction.addToBackStack(fragment.getClass().getName());

    transaction.commit();
}

そして、この例を完了するために、ロードしたときにタグを使用して、まったく同じフラグメントに戻ることができるメソッドを作成します。

public void backToFragment(final Fragment fragment) {

    // go back to something that was added to the backstack
    getSupportFragmentManager().popBackStackImmediate(
            fragment.getClass().getName(), 0);
    // use 0 or the below constant as flag parameter
    // FragmentManager.POP_BACK_STACK_INCLUSIVE);

}

これを実際に実装する場合、フラグメントパラメータにnullチェックを追加したいかもしれません;-)。

17
hcpl

2つのことを行う必要があります-FragmentTransactionにA-> Bの名前を付け、それを含むアクティビティのonBackPressed()をオーバーライドして、 FragmentManager#popBackStack(String name、int flags) Fragment Cを呼び出します例:

A-> Bからの移行

getSupportFragmentManager()
  .beginTransaction()
  .replace(R.id.container, new FragmentB(), "FragmentB")
  .addToBackStack("A_B_TAG")
  .commit();

B-> Cからの移行では、タグとして「FragmentC」を使用した同様のトランザクションが使用されます。

次に、含まれているアクティビティでonBackPressed()をオーバーライドします。

@Override
public void onBackPressed() {
  if (getSupportFragmentManager().findFragmentByTag("FragmentC") != null) {
    // I'm viewing Fragment C
    getSupportFragmentManager().popBackStack("A_B_TAG",
      FragmentManager.POP_BACK_STACK_INCLUSIVE);
  } else {
    super.onBackPressed();
  }
}
29
user697495