前人未踏の領域へ Androidアプリ開発編

Androidアプリ開発に関する調査メモ置き場。古い記事にはアプリ以外も含まれます。

ネストしたFragmentのバックスタック時挙動について

実装方法によっては発生しないのかもしれないけれど、自分の開発状況下で発生している問題について。

結論

子フラグメントをバックスタックから復元することはできる。しかし色々変更しすぎてもはや何が決め手になったかよくわからず。以下は本結論に繋がらない別な話である。

課題

あるFragment内に子フラグメントのViewまたはViewPagerを設置し、親フラグメント側のViewの画面遷移を行った際、バックボタン押下で前画面に戻った際に子フラグメントが再描画されず真っ白になる。できれば遷移前の状態を再現したい。

対応

あれこれ調べた結果、現時点では親のFragmentManagerでは子Viewの状態までは再現してくれない模様。なのでスクロールなどの細かな表示状態はともかく、再描画だけは行わせることにする。

子Fragmentの場合

親フラグメントのonCreateViewで子Fragmentが設置済みかを確認し、設置前ならadd、設置済みならreplaceする。FragmentManagerはgetChildFragmentManager()を使って取得。

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

       final FragmentManager cfm = getChildFragmentManager();
        Fragment f = cfm.findFragmentById(R.id.childFragmentContainer);
        FragmentTransaction ft = cfm.beginTransaction();
        if (f == null) {
            ft.add(R.id.childFragmentContainer, new Fragment(), "child");
        } else {
            ft.replace(R.id.childFragmentContainer, new Fragment(), "child");
        }
        ft.commit();
...
}
ViewPagerの場合

ViewPagerは内部でフラグメント管理を独自に行うため上記の方法が利用できない。しかしながら放っておくと描画に失敗するので古いデータが無いと思わせる必要がある。具体的にはPagerAdapterのrestoreStateを無視する

public class MyPagerAdapter extends FragmentStatePagerAdapter {
     @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
       // super.restoreState(state, loader);
       // 何もしない!!
    }
}

こうすると常にFragmentの再生成、再描画が行われ、空白のビューを見せられることはなくなる。


本当に辿り着きたかったゴールは前回表示状態の再現なのだけど、まあ仕方ない。