9

私が達成しようとしているシナリオ:

  1. 2つのフレームコンテナを使用したアクティビティの読み込み(アイテムのリストと詳細)。
  2. アプリの起動時に、listFrameにlistFragmentを追加し、detailsFrameコンテナーにいくつかの初期infoFragmentを追加します。
  3. 各詳細トランザクションをバックスタックに追加せずにリストアイテムをナビゲートします(infoFragmentのみをスタックに保持したい)。
  4. ユーザーが戻るボタン(戻る)を押すとすぐに、起動時に追加された最初のinfoFragmentにフォールバックします。
  5. シーケンシャルバックナビゲーションが許可されない場合、アプリは終了します。

私のコード:

        protected override void OnCreate(Bundle savedInstanceState)
        {
...
            var listFrag = new ListFragment();
            var infoFrag = new InfoFragment();
            var trans = FragmentManager.BeginTransaction();
            trans.Add(Resource.Id.listFrame, listFrag);
            trans.Add(Resource.Id.detailsFrame, infoFrag);
            trans.Commit();
...
        }

        public void OnItemSelected(int id)
        {
            var detailsFrag = DetailFragment.NewInstance(id);
            var trans = FragmentManager.BeginTransaction();
            trans.Replace(Resource.Id.detailsFrame, detailsFrag);
            if (FragmentManager.BackStackEntryCount == 0)
                {
                    trans.AddToBackStack(null);
                }
            trans.Commit();
        }

私の問題:

戻るボタンが押された後、infoFragは前のdetailFragとオーバーラップします!なんで?

4

5 に答える 5

12

あなたはこれを行うことができます:

if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
   getSupportFragmentManager().popBackStack(getSupportFragmentManager().getBackStackEntryAt(0).getId(), getSupportFragmentManager().POP_BACK_STACK_INCLUSIVE);
} else {
   super.onBackPressed();}

あなたの活動では、最初の断片を保持するようにします。

最初のフラグメントには、addToBackStackを含めるべきではありません。しかし、残りの部分では、はい。

于 2015-01-23T17:19:27.950 に答える
7

ブディウスによるとても素敵な説明。私は彼のアドバイスを読み、同様のナビゲーションを実装しました。これを他の人と共有したいと思います。

このようにフラグメントを置き換える代わりに:

Transaction.remove(detail1).add(detail2)
Transaction.remove(detail2).add(detail3)
Transaction.remove(detail3).add(detail4)

アクティビティレイアウトファイルにフラグメントコンテナレイアウトを追加しました。、、などのいずれかになります。LinearLayoutしたがって、作成のアクティビティで、次のようになりました。RelativeLayotFrameLayout

transaction.replace(R.id.HomeInputFragment, mainHomeFragment).commit();

mainHomeFragmentのように、戻るボタンを押したときに戻りたいフラグメントですinfoFrag。次に、次のすべてのトランザクションの前に、次のように入力します。

fragmentManager.popBackStackImmediate();
transaction.replace(R.id.HomeInputFragment, frag2).addToBackStack(null).commit();

また

fragmentManager.popBackStackImmediate();
transaction.replace(R.id.HomeInputFragment, frag3).addToBackStack(null).commit();

そうすれば、現在表示されているフラグメントを追跡する必要がありません。

于 2014-09-27T11:05:31.863 に答える
6

問題は、元のトランザクションにbacking2つのステップがあることです。

  • 削除するinfoFrag
  • 追加detailsFrag(これは、追加された最初の1つの詳細コンテナーです)

(ドキュメントがあるのでそれを知っていますThis is essentially the same as calling remove(Fragment) for all currently added fragments that were added with the same containerViewId and then add(int, Fragment, String) with the same arguments given here.

したがって、システムが元に戻すときは常に、1つのトランザクションがそれらの2つのステップを正確に元に戻し、最後detailFragに追加されたものについては何も言わないため、システムは何もしません。

私があなたのケースで考えることができる2つの可能な回避策があります:

  1. アクティビティの参照を最後に使用したdetailsFragを保持し、BackStackChangeリスナーを使用して、値が1から0に変更されるたびに(以前の値を追跡する必要があります)、残りの1つのフラグメントも削除します

  2. クリックリスナーごとに、popBackStackImmediatly()(前のトランザクションを削除するため)とaddToBackStack()すべてのトランザクションを実行する必要があります。この回避策では、setCustomAnimationマジックを使用して、画面上ですべてが見栄えがすることを確認することもできます(たとえば、前のフラグメントが再び表示されたり消えたりしないように、0から0の期間1のアルファアニメーションを使用します。

ps。フラグメントマネージャー/トランザクションは、.replace()アクションのバックスタックを処理する方法に対してもう少し賢いはずですが、それがそれを行う方法であることに同意します。

編集:

何が起こっているのかはこのようなものです(より明確にするために詳細に数字を追加しています)。それを覚えておいてください.replace() = .remove().add()

Transaction.remove(info).add(detail1).addToBackStack(null) // 1st time
Transaction.remove(detail1).add(detail2) // 2nd time
Transaction.remove(detail2).add(detail3) // 3rd time
Transaction.remove(detail3).add(detail4) // 4th time

これで、レイアウトにdetail4が追加されました。

< Press back button >
     System pops the back stack and find the following back entry to be reversed
         remove(info).add(detail1);
     so the system makes that transaction backward.
     tries to remove detail1 (is not there, so it ignores)
     re-add(info) // OVERLAP !!!

したがって、問題は、システムがdetail4があることを認識せず、トランザクションが.replace()であり、そこにあるものをすべて置き換えることになっていることです。

于 2013-01-11T17:12:00.017 に答える
0

onBackPressedをオーバーライドして、トランザクションを最初のフラグメントにコミットすることができます。

于 2013-01-10T23:55:36.493 に答える
0

私は推測していますが:

infoFragを最初のdetailsFragに置き換えるトランザクションをバックスタックに追加しました。

ただし、1番目のdetailsFragを2番目のdetailsFragに置き換えます。

この時点でクリックして戻ると、フラグメントマネージャは1番目のdetailsFragをinfoFragにきれいに置き換えることができません。これは、1番目のdetailsFragがすでに削除されて置き換えられているためです。

オーバーラップ動作が予想されるかどうかはわかりません。

Androidコアコードをデバッグして、それが何をしているのかを確認することをお勧めします。

Activity::onBackPressed()すべてのトランザクションをバックスタックに追加した後、自分でポップをオーバーライドして実行することなく、達成できるかどうかはわかりません。

于 2013-01-11T11:15:27.233 に答える