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 トランザクション - バックスタックの落とし穴
