modal_bottom_sheet
modal_bottom_sheet copied to clipboard
Modal Bottom Sheet get disposed when a new screen is push
First thank you for this great library.
I am using the plugin inside my router, it works extremely well but there is a weird behavior when pushing a new route. When pushing a new route from the modal page, the modal page itself get disposed, then get init again.
You can see the problem in this log generated from the video attached :
flutter: 🏠 _MyHomePageState initState
flutter: 📃 _ModalScreenState initState
flutter: 👷♂️ _NewScreenState initState
flutter: 📃 _ModalScreenState dispose <-- here is the error
flutter: 🌗 _LastScreenState initState
flutter: 🌗 _LastScreenState dispose
flutter: 📃 _ModalScreenState initState
flutter: 👷♂️ _NewScreenState dispose
flutter: 📃 _ModalScreenState dispose
https://user-images.githubusercontent.com/22376981/177247106-5fb97c11-89e0-4e3c-8d05-aee0527f1ad9.MP4
Minimal reproducible example
router
import 'package:example_modal_route_error/main.dart';
import 'package:flutter/material.dart';
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
class Routes {
static const home = '/';
static const modal = '/modal';
static const newScreen = '$modal/newScreen';
static const lastScreen = '$newScreen/lastScreen';
}
typedef RouteResolver = Route<dynamic> Function(RouteSettings settings);
class MyRouter {
static Route<dynamic>? onGenerateRoute(RouteSettings settings) {
final routePage = _pagesMap[settings.name];
return routePage?.call(settings);
}
static final _pagesMap = <String, RouteResolver>{
Routes.home: (settings) {
return MaterialPageRoute(
settings: settings,
builder: (context) => const MyHomePage(),
);
},
Routes.modal: (settings) {
return ModalBottomSheetRoute(
expanded: true,
settings: settings,
containerBuilder: (_, __, child) => BarBottomSheet(child: child),
builder: (context) => const ModalScreen(),
);
},
Routes.newScreen: (settings) {
return MaterialPageRoute(
settings: settings,
builder: (context) => const NewScreen(),
);
},
Routes.lastScreen: (settings) {
return MaterialPageRoute(
settings: settings,
builder: (context) => const LastScreen(),
);
},
};
}
main
import 'package:example_modal_route_error/router.dart';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter example error modal route',
theme: ThemeData(primarySwatch: Colors.blue),
onGenerateRoute: (RouteSettings settings) =>
MyRouter.onGenerateRoute(settings),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
print('🏠 _MyHomePageState initState');
super.initState();
}
@override
void dispose() {
print('🏠 _MyHomePageState dispose');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Flutter example error modal route')),
body: Center(
child: TextButton(
onPressed: () => Navigator.pushNamed(context, Routes.modal),
child: const Text('Tap to open modal'),
),
),
);
}
}
class ModalScreen extends StatefulWidget {
const ModalScreen({super.key});
@override
State<ModalScreen> createState() => _ModalScreenState();
}
class _ModalScreenState extends State<ModalScreen> {
@override
void initState() {
print('📃 _ModalScreenState initState');
super.initState();
}
@override
void dispose() {
print('📃 _ModalScreenState dispose');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('📃 Modal screen')),
body: Center(
child: TextButton(
onPressed: () => Navigator.pushNamed(context, Routes.newScreen),
child: const Text('Tap to push new route'),
),
),
);
}
}
class NewScreen extends StatefulWidget {
const NewScreen({super.key});
@override
State<NewScreen> createState() => _NewScreenState();
}
class _NewScreenState extends State<NewScreen> {
@override
void initState() {
print('👷♂️ _NewScreenState initState');
super.initState();
}
@override
void dispose() {
print('👷♂️ _NewScreenState dispose');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('👷♂️ New screen')),
body: Center(
child: TextButton(
onPressed: () => Navigator.pushNamed(context, Routes.lastScreen),
child: const Text('Tap to push last route'),
),
),
);
}
}
class LastScreen extends StatefulWidget {
const LastScreen({super.key});
@override
State<LastScreen> createState() => _LastScreenState();
}
class _LastScreenState extends State<LastScreen> {
@override
void initState() {
print('🌗 _LastScreenState initState');
super.initState();
}
@override
void dispose() {
print('🌗 _LastScreenState dispose');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('🌗 Last screen')),
body: const Center(child: Text('This is the last screen')),
);
}
}
i am using a the latest version of the plugin 2.1.0 and flutter 3.0.3.
This error does not occurs while using 2.0.1 version.
I can confirm this behaviour. Reverting to 2.0.1 and you don't get a dispose. If the pane you push is something like tab view, you basically lose all state of which tab was pushed etc.