Showing
5 changed files
with
64 additions
and
156 deletions
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | import 'package:get/get.dart'; | 2 | import 'package:get/get.dart'; |
| 3 | 3 | ||
| 4 | -// void main() { | ||
| 5 | -// runApp(const MyApp()); | ||
| 6 | -// } | ||
| 7 | - | ||
| 8 | -// class MyApp extends StatelessWidget { | ||
| 9 | -// const MyApp({Key? key}) : super(key: key); | ||
| 10 | - | ||
| 11 | -// @override | ||
| 12 | -// Widget build(BuildContext context) { | ||
| 13 | -// return GetMaterialApp( | ||
| 14 | -// theme: ThemeData(useMaterial3: true), | ||
| 15 | -// debugShowCheckedModeBanner: false, | ||
| 16 | -// enableLog: true, | ||
| 17 | -// logWriterCallback: Logger.write, | ||
| 18 | -// initialRoute: AppPages.INITIAL, | ||
| 19 | -// getPages: AppPages.routes, | ||
| 20 | -// locale: TranslationService.locale, | ||
| 21 | -// fallbackLocale: TranslationService.fallbackLocale, | ||
| 22 | -// translations: TranslationService(), | ||
| 23 | -// ); | ||
| 24 | -// } | ||
| 25 | -// } | ||
| 26 | - | ||
| 27 | -/// Nav 2 snippet | ||
| 28 | void main() { | 4 | void main() { |
| 29 | - runApp(const MyApp()); | 5 | + runApp(MyApp()); |
| 30 | } | 6 | } |
| 31 | 7 | ||
| 32 | class MyApp extends StatelessWidget { | 8 | class MyApp extends StatelessWidget { |
| 33 | - const MyApp({Key? key}) : super(key: key); | ||
| 34 | - | 9 | +// This widget is the root of your application. |
| 35 | @override | 10 | @override |
| 36 | Widget build(BuildContext context) { | 11 | Widget build(BuildContext context) { |
| 37 | return GetMaterialApp( | 12 | return GetMaterialApp( |
| 38 | - getPages: [ | ||
| 39 | - GetPage( | ||
| 40 | - participatesInRootNavigator: true, | ||
| 41 | - name: '/first', | ||
| 42 | - page: () => const First()), | ||
| 43 | - GetPage( | ||
| 44 | - name: '/second', | ||
| 45 | - page: () => const Second(), | ||
| 46 | - transition: Transition.downToUp, | ||
| 47 | - ), | ||
| 48 | - GetPage( | ||
| 49 | - name: '/third', | ||
| 50 | - page: () => const Third(), | ||
| 51 | - ), | ||
| 52 | - ], | 13 | + title: 'Scaffold demo', |
| 14 | + theme: ThemeData( | ||
| 15 | + primarySwatch: Colors.blue, | ||
| 16 | + ), | ||
| 17 | + home: MyHomePage(), | ||
| 53 | debugShowCheckedModeBanner: false, | 18 | debugShowCheckedModeBanner: false, |
| 54 | ); | 19 | ); |
| 55 | } | 20 | } |
| 56 | } | 21 | } |
| 57 | 22 | ||
| 58 | -class FirstController extends GetxController { | ||
| 59 | - @override | ||
| 60 | - void onClose() { | ||
| 61 | - print('on close first'); | ||
| 62 | - super.onClose(); | ||
| 63 | - } | ||
| 64 | -} | ||
| 65 | - | ||
| 66 | -class First extends StatelessWidget { | ||
| 67 | - const First({Key? key}) : super(key: key); | ||
| 68 | - | 23 | +class MyHomePage extends StatelessWidget { |
| 69 | @override | 24 | @override |
| 70 | Widget build(BuildContext context) { | 25 | Widget build(BuildContext context) { |
| 71 | - print('First rebuild'); | ||
| 72 | - Get.put(FirstController()); | ||
| 73 | return Scaffold( | 26 | return Scaffold( |
| 74 | appBar: AppBar( | 27 | appBar: AppBar( |
| 75 | - title: const Text('page one'), | ||
| 76 | - leading: IconButton( | ||
| 77 | - icon: const Icon(Icons.more), | 28 | + title: Text('Test'), |
| 29 | + centerTitle: true, | ||
| 30 | + backgroundColor: Colors.green, | ||
| 31 | + ), | ||
| 32 | + bottomNavigationBar: SizedBox( | ||
| 33 | + width: double.infinity, | ||
| 34 | + child: ElevatedButton( | ||
| 35 | + child: Text('Tap me when Snackbar appears'), | ||
| 78 | onPressed: () { | 36 | onPressed: () { |
| 79 | - Get.snackbar( | ||
| 80 | - 'title', | ||
| 81 | - "message", | ||
| 82 | - mainButton: | ||
| 83 | - TextButton(onPressed: () {}, child: const Text('button')), | ||
| 84 | - isDismissible: false, | ||
| 85 | - ); | ||
| 86 | - // print('THEME CHANGED'); | ||
| 87 | - // Get.changeTheme( | ||
| 88 | - // Get.isDarkMode ? ThemeData.light() : ThemeData.dark()); | 37 | + print('This should clicked'); |
| 89 | }, | 38 | }, |
| 90 | ), | 39 | ), |
| 91 | ), | 40 | ), |
| 92 | body: Center( | 41 | body: Center( |
| 93 | - child: SizedBox( | ||
| 94 | - height: 300, | ||
| 95 | - width: 300, | ||
| 96 | - child: ElevatedButton( | ||
| 97 | - onPressed: () { | ||
| 98 | - Get.toNamed('/second?id=123'); | ||
| 99 | - }, | ||
| 100 | - child: const Text('next screen'), | ||
| 101 | - ), | ||
| 102 | - ), | ||
| 103 | - ), | ||
| 104 | - ); | ||
| 105 | - } | ||
| 106 | -} | ||
| 107 | - | ||
| 108 | -class SecondController extends GetxController { | ||
| 109 | - final textEdit = TextEditingController(); | ||
| 110 | - @override | ||
| 111 | - void onClose() { | ||
| 112 | - print('on close second'); | ||
| 113 | - textEdit.dispose(); | ||
| 114 | - super.onClose(); | ||
| 115 | - } | ||
| 116 | -} | ||
| 117 | - | ||
| 118 | -class Second extends StatelessWidget { | ||
| 119 | - const Second({Key? key}) : super(key: key); | ||
| 120 | - | ||
| 121 | - @override | ||
| 122 | - Widget build(BuildContext context) { | ||
| 123 | - final controller = Get.put(SecondController()); | ||
| 124 | - print('second rebuild'); | ||
| 125 | - return Scaffold( | ||
| 126 | - appBar: AppBar( | ||
| 127 | - title: Text('page two ${Get.parameters["id"]}'), | ||
| 128 | - ), | ||
| 129 | - body: Center( | ||
| 130 | - child: Column( | ||
| 131 | - children: [ | ||
| 132 | - Expanded( | ||
| 133 | - child: TextField( | ||
| 134 | - controller: controller.textEdit, | ||
| 135 | - )), | ||
| 136 | - SizedBox( | ||
| 137 | - height: 300, | ||
| 138 | - width: 300, | ||
| 139 | - child: ElevatedButton( | ||
| 140 | - onPressed: () {}, | ||
| 141 | - child: const Text('next screen'), | ||
| 142 | - ), | ||
| 143 | - ), | ||
| 144 | - ], | ||
| 145 | - ), | ||
| 146 | - ), | ||
| 147 | - ); | ||
| 148 | - } | ||
| 149 | -} | ||
| 150 | - | ||
| 151 | -class Third extends StatelessWidget { | ||
| 152 | - const Third({Key? key}) : super(key: key); | ||
| 153 | - | ||
| 154 | - @override | ||
| 155 | - Widget build(BuildContext context) { | ||
| 156 | - return Scaffold( | ||
| 157 | - backgroundColor: Colors.red, | ||
| 158 | - appBar: AppBar( | ||
| 159 | - title: const Text('page three'), | ||
| 160 | - ), | ||
| 161 | - body: Center( | ||
| 162 | - child: SizedBox( | ||
| 163 | - height: 300, | ||
| 164 | - width: 300, | ||
| 165 | - child: ElevatedButton( | ||
| 166 | - onPressed: () {}, | ||
| 167 | - child: const Text('go to first screen'), | ||
| 168 | - ), | 42 | + child: ElevatedButton( |
| 43 | + child: Text('Open Snackbar'), | ||
| 44 | + onPressed: () { | ||
| 45 | + Get.snackbar( | ||
| 46 | + "Snackbar Showed", | ||
| 47 | + "Please click the button on BottomNavigationBar", | ||
| 48 | + icon: Icon(Icons.check, color: Colors.green), | ||
| 49 | + backgroundColor: Colors.white, | ||
| 50 | + snackStyle: SnackStyle.floating, | ||
| 51 | + borderRadius: 20, | ||
| 52 | + isDismissible: false, | ||
| 53 | + snackPosition: SnackPosition.bottom, | ||
| 54 | + margin: EdgeInsets.fromLTRB(50, 15, 50, 15), | ||
| 55 | + ); | ||
| 56 | + }, | ||
| 169 | ), | 57 | ), |
| 170 | ), | 58 | ), |
| 171 | ); | 59 | ); |
| @@ -341,13 +341,12 @@ class GetRootState extends State<GetRoot> with WidgetsBindingObserver { | @@ -341,13 +341,12 @@ class GetRootState extends State<GetRoot> with WidgetsBindingObserver { | ||
| 341 | void onClose() { | 341 | void onClose() { |
| 342 | config.onDispose?.call(); | 342 | config.onDispose?.call(); |
| 343 | Get.clearTranslations(); | 343 | Get.clearTranslations(); |
| 344 | + config.snackBarQueue.disposeControllers(); | ||
| 344 | RouterReportManager.instance.clearRouteKeys(); | 345 | RouterReportManager.instance.clearRouteKeys(); |
| 345 | RouterReportManager.dispose(); | 346 | RouterReportManager.dispose(); |
| 346 | Get.resetInstance(clearRouteBindings: true); | 347 | Get.resetInstance(clearRouteBindings: true); |
| 347 | _controller = null; | 348 | _controller = null; |
| 348 | ambiguate(Engine.instance)!.removeObserver(this); | 349 | ambiguate(Engine.instance)!.removeObserver(this); |
| 349 | - config.snackBarQueue.cancelAllJobs(); | ||
| 350 | - config.snackBarQueue.disposeControllers(); | ||
| 351 | } | 350 | } |
| 352 | 351 | ||
| 353 | @override | 352 | @override |
| @@ -19,6 +19,13 @@ class GetSnackBar extends StatefulWidget { | @@ -19,6 +19,13 @@ class GetSnackBar extends StatefulWidget { | ||
| 19 | /// The title displayed to the user | 19 | /// The title displayed to the user |
| 20 | final String? title; | 20 | final String? title; |
| 21 | 21 | ||
| 22 | + /// Defines how the snack bar area, including margin, will behave during hit testing. | ||
| 23 | + /// | ||
| 24 | + /// If this property is null and [margin] is not null, then [HitTestBehavior.deferToChild] is used by default. | ||
| 25 | + /// | ||
| 26 | + /// Please refer to [HitTestBehavior] for a detailed explanation of every behavior. | ||
| 27 | + final HitTestBehavior? hitTestBehavior; | ||
| 28 | + | ||
| 22 | /// The direction in which the SnackBar can be dismissed. | 29 | /// The direction in which the SnackBar can be dismissed. |
| 23 | /// | 30 | /// |
| 24 | /// Default is [DismissDirection.down] when | 31 | /// Default is [DismissDirection.down] when |
| @@ -203,6 +210,7 @@ class GetSnackBar extends StatefulWidget { | @@ -203,6 +210,7 @@ class GetSnackBar extends StatefulWidget { | ||
| 203 | this.overlayColor = Colors.transparent, | 210 | this.overlayColor = Colors.transparent, |
| 204 | this.userInputForm, | 211 | this.userInputForm, |
| 205 | this.snackbarStatus, | 212 | this.snackbarStatus, |
| 213 | + this.hitTestBehavior, | ||
| 206 | }) : super(key: key); | 214 | }) : super(key: key); |
| 207 | 215 | ||
| 208 | @override | 216 | @override |
| @@ -245,6 +245,7 @@ class SnackbarController { | @@ -245,6 +245,7 @@ class SnackbarController { | ||
| 245 | snackbar.onHover?.call(snackbar, SnackHoverState.entered), | 245 | snackbar.onHover?.call(snackbar, SnackHoverState.entered), |
| 246 | onExit: (_) => snackbar.onHover?.call(snackbar, SnackHoverState.exited), | 246 | onExit: (_) => snackbar.onHover?.call(snackbar, SnackHoverState.exited), |
| 247 | child: GestureDetector( | 247 | child: GestureDetector( |
| 248 | + behavior: snackbar.hitTestBehavior ?? HitTestBehavior.deferToChild, | ||
| 248 | onTap: snackbar.onTap != null | 249 | onTap: snackbar.onTap != null |
| 249 | ? () => snackbar.onTap?.call(snackbar) | 250 | ? () => snackbar.onTap?.call(snackbar) |
| 250 | : null, | 251 | : null, |
| @@ -263,6 +264,7 @@ class SnackbarController { | @@ -263,6 +264,7 @@ class SnackbarController { | ||
| 263 | 264 | ||
| 264 | Widget _getDismissibleSnack(Widget child) { | 265 | Widget _getDismissibleSnack(Widget child) { |
| 265 | return Dismissible( | 266 | return Dismissible( |
| 267 | + behavior: snackbar.hitTestBehavior ?? HitTestBehavior.opaque, | ||
| 266 | direction: snackbar.dismissDirection ?? _getDefaultDismissDirection(), | 268 | direction: snackbar.dismissDirection ?? _getDefaultDismissDirection(), |
| 267 | resizeDuration: null, | 269 | resizeDuration: null, |
| 268 | confirmDismiss: (_) { | 270 | confirmDismiss: (_) { |
| @@ -382,10 +384,19 @@ class SnackBarQueue { | @@ -382,10 +384,19 @@ class SnackBarQueue { | ||
| 382 | _snackbarList.clear(); | 384 | _snackbarList.clear(); |
| 383 | } | 385 | } |
| 384 | 386 | ||
| 385 | - Future<void> disposeControllers() async { | 387 | + void disposeControllers() { |
| 388 | + if (_currentSnackbar != null) { | ||
| 389 | + _currentSnackbar?._removeOverlay(); | ||
| 390 | + _currentSnackbar?._controller.dispose(); | ||
| 391 | + _snackbarList.remove(_currentSnackbar); | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + _queue.cancelAllJobs(); | ||
| 395 | + | ||
| 386 | for (var element in _snackbarList) { | 396 | for (var element in _snackbarList) { |
| 387 | element._controller.dispose(); | 397 | element._controller.dispose(); |
| 388 | } | 398 | } |
| 399 | + _snackbarList.clear(); | ||
| 389 | } | 400 | } |
| 390 | 401 | ||
| 391 | Future<void> closeCurrentJob() async { | 402 | Future<void> closeCurrentJob() async { |
| @@ -107,13 +107,15 @@ void main() { | @@ -107,13 +107,15 @@ void main() { | ||
| 107 | }); | 107 | }); |
| 108 | 108 | ||
| 109 | testWidgets("test snackbar dismissible", (tester) async { | 109 | testWidgets("test snackbar dismissible", (tester) async { |
| 110 | - const dismissDirection = DismissDirection.vertical; | 110 | + const dismissDirection = DismissDirection.down; |
| 111 | const snackBarTapTarget = Key('snackbar-tap-target'); | 111 | const snackBarTapTarget = Key('snackbar-tap-target'); |
| 112 | 112 | ||
| 113 | const GetSnackBar getBar = GetSnackBar( | 113 | const GetSnackBar getBar = GetSnackBar( |
| 114 | + key: ValueKey('dismissible'), | ||
| 114 | message: 'bar1', | 115 | message: 'bar1', |
| 115 | duration: Duration(seconds: 2), | 116 | duration: Duration(seconds: 2), |
| 116 | isDismissible: true, | 117 | isDismissible: true, |
| 118 | + snackPosition: SnackPosition.bottom, | ||
| 117 | dismissDirection: dismissDirection, | 119 | dismissDirection: dismissDirection, |
| 118 | ); | 120 | ); |
| 119 | 121 | ||
| @@ -149,14 +151,14 @@ void main() { | @@ -149,14 +151,14 @@ void main() { | ||
| 149 | await tester.tap(find.byKey(snackBarTapTarget)); | 151 | await tester.tap(find.byKey(snackBarTapTarget)); |
| 150 | await tester.pumpAndSettle(); | 152 | await tester.pumpAndSettle(); |
| 151 | 153 | ||
| 152 | - // expect(Get.isSnackbarOpen, true); | ||
| 153 | - // await tester.pump(const Duration(milliseconds: 500)); | ||
| 154 | - // expect(find.byWidget(getBar), findsOneWidget); | ||
| 155 | - // await tester.ensureVisible(find.byWidget(getBar)); | ||
| 156 | - // await tester.drag(find.byWidget(getBar), const Offset(0.0, 50.0)); | ||
| 157 | - // await tester.pump(const Duration(milliseconds: 500)); | ||
| 158 | - | ||
| 159 | - // expect(Get.isSnackbarOpen, false); | 154 | + expect(Get.isSnackbarOpen, true); |
| 155 | + await tester.pump(const Duration(milliseconds: 500)); | ||
| 156 | + expect(find.byWidget(getBar), findsOneWidget); | ||
| 157 | + await tester.ensureVisible(find.byWidget(getBar)); | ||
| 158 | + await tester.drag(find.byType(Dismissible), const Offset(0.0, 50.0)); | ||
| 159 | + await tester.pumpAndSettle(); | ||
| 160 | + await tester.pump(const Duration(milliseconds: 500)); | ||
| 161 | + expect(Get.isSnackbarOpen, false); | ||
| 160 | }); | 162 | }); |
| 161 | 163 | ||
| 162 | testWidgets("test snackbar onTap", (tester) async { | 164 | testWidgets("test snackbar onTap", (tester) async { |
-
Please register or login to post a comment