Androidで戻るボタン(BackKey)を押した際の挙動でハマったので、その実装方法を記載します。
[前提]
画面の作りは、Fragmentを利用。
Fragmentの切り替えは普通にこんな感じで実装。
mFragmentManager.beginTransaction()
.replace(R.id.container, myFragment).commit();
[ゴール]
戻るボタンを押した際に、一つ前のFragmentを再度表示したい。
[問題]
戻るボタンを押すとActivityがバックグラウンド実行状態に移行してしまう。(ホームボタンが押された時と同じ挙動をする。)
[解決法]
1.BackStackへの追加
ネットで情報を調べて見ると、次のFragmentをcommitする前にBackStackへ現在のFragmentを追加する必要があるとのこと。
mFragmentManager.beginTransaction()
.addToBackStack(null) // ここでBackStackに追加している。
.replace(R.id.container, myFragment).commit();
これで解決するかと思ったが、以前として同じ挙動のまま。
そこでもう少し調べてみることに。
2.onBackPressedの実装
戻るボタンが押されるとイベントが発生するので、それをキャッチして元のFragmentへ戻るようにコーディングすればよさそう。
FragmentのViewに対してOnClickListenerでリスナー登録する例が有ったが、戻るボタンを押してもうまくListenerが呼ばれない。
Activity側で実装をするとよいとの情報があったので、以下のように実装しました。
@Override
public void onBackPressed() {
// super.onBackPressedを呼んではいけない(Activityを終了させてしまうため)
int backStackCnt = getFragmentManager().getBackStackEntryCount();
if (backStackCnt != 0) {
getFragmentManager().popBackStack(); // BackStackに乗っているFragmentを戻す
}
}
コード内にコメントを記載しましたが、戻るボタンを押すとアプリが終了してしまった原因はActivityで元々定義されているonBackPressedの処理でした。
これをOverrideすることで、無事解決しました。
なお、ここではmFragmentManager.beginTransaction()の後のFragment設定時に.replaceとしているため、BackStackがpopされたときには元のFragmentがリロードされます。
元のFragmentで初回表示時に通信等を行っている場合は、その処理も再度発生してしまいます。(FragmentのCreateから再実行される)
replaceではなくaddを利用すれば、元のFragmentは破棄されず裏に隠れた状態になるため、リロードされません。
実装方法選択時には、リロード時の負荷/ユーザビリティとFragmentの保持に必要なメモリ量の兼ね合い化となります。