FlutterでAndroidのFragment Transaction的な
親の顔より見たアレを Flutter でやります.
override fun onCreate(savedInstanceState: Bundle?) { val fragment = MainFragment.newInstance() supportFragmentManager.beginTransaction() .replace(R.id.content, fragment) .addToBackStack(null).commit() supportFragmentManager.addOnBackStackChangedListener { if (supportFragmentManager.backStackEntryCount > 0) { supportActionBar?.setDisplayHomeAsUpEnabled(true) } else { supportActionBar?.setDisplayHomeAsUpEnabled(false) }}state_notifier を使ってやっていきます.
切り替える Fragment 相当の View の種類の Enum
enum ViewType { Main, Sub,}StateNotifier を用意します.
@freezedabstract class AppViewState with _$AppViewState { const factory AppViewState({ @Default(ViewType.Main) viewType, }) = _AppViewState;}class AppViewStateNotifier extends StateNotifier<AppViewState> { AppViewStateNotifier() : super(const AppViewState()) {} void setViewType(ViewType viewType) { state = state.copyWith(viewType: viewType); }}以下が Fragament 相当の View を持つ View です. WillPopScope は Activity でいう onBackPressed を実現する View だと思ってください. onWillPop で現在の View が Sub だった場合 MainView に切り替えするようにします. AppBar#leading でも View が Sub だったときは back_arrow をセットするようにして setDisplayHomeAsUpEnabled(true) 相当になるようにします. 今回は View が 2 つなのでこんな感じですが,View が 3 つとかの場合は Map とかにしてよしなにするだけですね.
class AppView extends StatelessWidget { @override Widget build(BuildContext context) { var viewType = context.select<AppViewState, ViewType>( (state) => state.viewType); return WillPopScope( onWillPop: () async { if (viewType == ViewType.Main) { Navigator.of(context).pop(); } else { context .read<AppViewStateNotifier>() .setViewType(ViewType.Main); } return false; }, child: Scaffold( appBar: AppBar( title: const Text('App'), leading: viewType == ViewType.Main ? null : IconButton( icon: Icon( Icons.arrow_back, color: Colors.white, ), onPressed: () { context .read<AppViewStateNotifier>() .setViewType(ViewType.Main); }), ), body: Container( child: viewType == ViewType.Main ? _MainView() : _SubView(), ), ), ); }}View を Sub に切り替えるときは ViewType.Sub を渡すだけです.
class _MainView extends StatelessWidget { @override Widget build(BuildContext context) { return Container( child: ListView( children: <Widget>[ ListTile( title: Text('Sub'), onTap: () { context .read<AppViewStateNotifier>() .setViewType(ViewType.Sub); }, ), ], ), ); }}もっといいやりかたありそう.