Androidアプリを作るとき昔はActivityを複数作ってIntentで画面切替をしていた。
今は一つのActivityの中にFragmentを突っ込んでFragmentを切り替えることで画面切替をするようにしている。(一般的にもこの方法が今はメジャーなはず)
FragmentA、FragmentB、FragmentCと3つのFragmentがあったとして、
Fragmentでの画面切替は普通こんな感じで行う。
FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); transaction.replace(R.id.container, FragmentA.newInstance() ); transaction.addToBackStack(null); transaction.commit();
commit時にBackStackに積んでいるので
[A] -> [B] -> [C] と画面切替をした後バックキーを押す度に
[C] -> [B]
[B] -> [A]
と切り替わる。
しかし、一度に [C] -> [A]に戻りたいときどうすれば良いかを分らなかった。
調べたところ、BackStackはFragmentのインスタンスを保存しているのではなく、transactionで行ったことを記録しているだけらしく、popBackStack()が実行されると記録されたことと逆のことが実行される。
例えば、replace(FragmentB)(中身はremove(FragmentA)してadd(FragmentB))が記録されていた場合
その逆のremove(FragmentB)してadd(FragmentA)が実行されるらしい。
知らなかったーーーー。
それならば、話は簡単で[C] -> [A]に一度のバックキーで戻るにはFragmentBackStackの数が変わったことをイベントトリガとして、BackStackの数が0に成るまでpopBackStackを呼んでやれば良い。
FragmentBackStackの数の変更はFragmentManager.OnBackStackChangedListnerを実現することで検知できる。
以下サンプルコード
public class MainActivity implements FragmentManager.OnBackStackChangedListener{ private int fragmentBackStackCnt = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction().add(R.id.container, FragmentA.newInstance()).commit(); fragmentManager.addOnBackStackChangedListener(this); } @Override public void onBackStackChanged() { FragmentManager fragmentManager = getFragmentManager(); int count = fragmentManager.getBackStackEntryCount(); if (fragmentBackStackCnt > count && count != 0) { // backStackが0になる(検索画面になるまで)fragmentをpopする fragmentManager.popBackStack(); } fragmentBackStackCnt = count; } }
参考ページ:
Android Fragment トランザクション - バックスタックの落とし穴