I'm learning Flutter by following the relatively recent tutorial (made in February - LINK) and while I wrote the same code as author I'm getting the following exception:
======== Exception caught by widgets library =======================================================
The following FirebaseException was thrown building FutureBuilder<FirebaseApp>(dirty, state: _FutureBuilderState<FirebaseApp>#881ee):
[core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()
The relevant error-causing widget was:
FutureBuilder<FirebaseApp> FutureBuilder:file:///C:/Users/Mrky/Desktop/Sve/Faks/10_semestar/mynotes/lib/main.dart:30:13
When the exception was thrown, this was the stack:
#0 MethodChannelFirebase.app (package:firebase_core_platform_interface/src/method_channel/method_channel_firebase.dart:173:5)
#1 Firebase.app (package:firebase_core/src/firebase.dart:53:41)
#2 FirebaseAuth.instance (package:firebase_auth/src/firebase_auth.dart:38:47)
#3 HomePage.build.<anonymous closure> (package:mynotes/main.dart:37:34)
#4 _FutureBuilderState.build (package:flutter/src/widgets/async.dart:615:55)
#5 StatefulElement.build (package:flutter/src/widgets/framework.dart:4919:27)
#6 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4806:15)
#7 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#8 Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#9 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
#10 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:891:21)
#11 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370:5)
#12 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15)
#13 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083:9)
#14 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:997:5)
#18 _invoke (dart:ui/hooks.dart:151:10)
#19 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
#20 _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
==========================================================================================
The code that I have currently written is:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:mynotes/firebase_options.dart';
import 'package:mynotes/views/login_view.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(
MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const HomePage(),
),
);
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
body: FutureBuilder(
future: Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.done:
print(FirebaseAuth.instance.currentUser);
return const Text('Done');
default:
return const Text('Loading...');
}
},
),
);
}
}
As it is visible I have Firebase.initializeApp inside future of FutureBuilder. Also If I comment out the line print(FirebaseAuth.instance.currentUser); the app will show text Done without any problem.
Run flutter clean, then add the dart pub package firebase_core with the command flutter pub add firebase_core. Finally, run flutter pub get to resolve all the dependencies.
Make your void function async and add the following lines inside your void main.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
Related
This is my code and the error I'm getting in Visual Studio Code. It used to work before, not sure if an update messed it up. I have other Flutter programs running just fine, not sure what the problem is with this one.
// 1) Create a new Flutter App (in this project) and output an AppBar and some text
// below it
// 2) Add a button which changes the text (to any other text of your choice)
// 3) Split the app into three widgets: App, TextControl & Text
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
// void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
Random _stringIndex = new Random();
var _randomStringIndex;
final _strings = const [
"Hello",
"This is a string",
"This is random",
];
void _changeText() {
setState(() {
_randomStringIndex = _stringIndex.nextInt(_strings.length);
});
print(_strings[_randomStringIndex]);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My First App'),
),
body: Center(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
RaisedButton(
onPressed: _changeText,
),
Text(
_strings[_randomStringIndex],
),
],
),
),
),
),
);
}
}
Launching lib/main.dart on Android SDK built for x86 in debug mode...
✓ Built build/app/outputs/apk/debug/app-debug.apk. Connecting to VM
Service at ws://127.0.0.1:40605/I0TqLbk5jw4=/ws D/EGL_emulation(
7151): eglMakeCurrent: 0xe1b1a3c0: ver 2 0 (tinfo 0xe1b0f770)
D/eglCodecCommon( 7151): setVertexArrayObject: set vao to 0 (0) 1 0
I/flutter ( 7151): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY
╞═══════════════════════════════════════════════════════════ I/flutter
( 7151): The following ArgumentError was thrown building MyApp(dirty,
state: _MyAppState#202c3): I/flutter ( 7151): Invalid argument(s)
I/flutter ( 7151): I/flutter ( 7151): The relevant error-causing
widget was: I/flutter ( 7151): MyApp I/flutter ( 7151):
package:flutter_assignment/main.dart:11 I/flutter ( 7151): I/flutter (
7151): When the exception was thrown, this was the stack: I/flutter (
7151): #0 List.[] (dart:core-patch/array.dart:169:52) I/flutter
( 7151): #1 _MyAppState.build
package:flutter_assignment/main.dart:57 I/flutter ( 7151): #2
StatefulElement.build package:flutter/…/widgets/framework.dart:4619
I/flutter ( 7151): #3 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4502 I/flutter ( 7151): #4
StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:4675 I/flutter ( 7151): #5
Element.rebuild package:flutter/…/widgets/framework.dart:4218
I/flutter ( 7151): #6 ComponentElement._firstBuild
package:flutter/…/widgets/framework.dart:4481 I/flutter ( 7151): #7
StatefulElement._firstBuild
package:flutter/…/widgets/framework.dart:4666 I/flutter ( 7151): #8
ComponentElement.mount package:flutter/…/widgets/framework.dart:4476
I/flutter ( 7151): #9 Element.inflateWidget
package:flutter/…/widgets/framework.dart:3446 I/flutter ( 7151): #10
Element.updateChild package:flutter/…/widgets/framework.dart:3214
I/flutter ( 7151): #11 RenderObjectToWidgetElement._rebuild
package:flutter/…/widgets/binding.dart:1148 I/flutter ( 7151): #12
RenderObjectToWidgetElement.mount
package:flutter/…/widgets/binding.dart:1119 I/flutter ( 7151): #13
RenderObjectToWidgetAdapter.attachToRenderTree.
package:flutter/…/widgets/binding.dart:1061 I/flutter ( 7151): #14
BuildOwner.buildScope package:flutter/…/widgets/framework.dart:2607
I/flutter ( 7151): #15
RenderObjectToWidgetAdapter.attachToRenderTree
package:flutter/…/widgets/binding.dart:1060 I/flutter ( 7151): #16
WidgetsBinding.attachRootWidget
package:flutter/…/widgets/binding.dart:941
You can copy paste run full code below
You need to init _randomStringIndex
code snippet
var _randomStringIndex = 0;
working demo
full code
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
// void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
Random _stringIndex = new Random();
var _randomStringIndex = 0;
final _strings = const [
"Hello",
"This is a string",
"This is random",
];
void _changeText() {
setState(() {
_randomStringIndex = _stringIndex.nextInt(_strings.length);
});
print(_strings[_randomStringIndex]);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My First App'),
),
body: Center(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
RaisedButton(
onPressed: _changeText,
),
Text(
_strings[_randomStringIndex],
),
],
),
),
),
),
);
}
}
Try to run this command inside your project (terminal):
flutter clean
and then run it again!
I am trying to take an image and send it to IBM Watson to classify it into one of 3 custom classifiers. Below is all my code.
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter_ibm_watson/flutter_ibm_watson.dart';
import 'package:ibm_visual_recog_img_file/connection.dart';
import 'package:ourearth2020/screens/Community.dart';
import 'package:path/path.dart';
import 'dart:async';
import 'package:image_picker/image_picker.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:path_provider/path_provider.dart';
class VisualPage extends StatefulWidget {
#override
_VisualPageState createState() => _VisualPageState();
}
class _VisualPageState extends State<VisualPage> {
CameraController _controller;
List cameras;
String path;
var galleryImage;
CameraDescription cameraDescription;
Future initCamera() async {
cameras = await availableCameras();
var frontCamera = cameras.first;
_controller = CameraController(frontCamera, ResolutionPreset.high);
try {
await _controller.initialize();
} catch (e) {}
print('Controller Is Init:' + _controller.value.isInitialized.toString());
displayPreview();
}
bool displayPreview() {
if (_controller == null || !_controller.value.isInitialized) {
return false;
} else {
return true;
}
}
Future getImageFromGallery() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
galleryImage = image;
});
print('GALLERY IMAGE' + galleryImage.toString());
return galleryImage;
}
#override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
#override
void initState() {
super.initState();
print('Running');
initCamera();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Stack(children: [
displayPreview()
? AspectRatio(
aspectRatio: MediaQuery.of(context).size.width /
MediaQuery.of(context).size.height,
child: CameraPreview(_controller),
)
: Container(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.yellow),
),
),
Positioned(
top: MediaQuery.of(context).size.height - 120,
child: GestureDetector(
onTap: () async {
await getImageFromGallery();
Navigator.push(context, MaterialPageRoute(builder: (context) =>
DisplayPicture(image: galleryImage)
));
},
child: Icon(
Icons.image,
color: Colors.white,
size: 60,
)),
),
Positioned(
top: MediaQuery.of(context).size.height - 120,
left: MediaQuery.of(context).size.width / 2.2,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
child: Container(
child: Icon(
Icons.camera,
color: Colors.white,
size: 60,
)),
onTap: () async {
final path = (await getTemporaryDirectory()).path +
'${DateTime.now()}.png';
try {
await _controller.takePicture(path);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
DisplayPicture(imagePath: path)));
} catch (e) {
print('EEEE' + e);
}
}))
]));
}
}
class DisplayPicture extends StatelessWidget {
String imagePath;
File image;
String _text;
// File file = File(imagePath)
DisplayPicture({this.imagePath, this.image});
visualImageClassifier(File image) async{
IamOptions options = await IamOptions(iamApiKey: "NRDjngCby2d-pSHOPyWQJxhuB6vOY2uOTCX6KV2BCfwB", url: "https://api.us-south.visual-recognition.watson.cloud.ibm.com/instances/ef286f4e-84c7-44e0-b63d-a6a49a142a30").build();
VisualRecognition visualRecognition = new VisualRecognition(iamOptions: options, language: Language.ENGLISH); // Language.ENGLISH is language response
ClassifiedImages classifiedImages = await visualRecognition.classifyImageFile(image.path);
print(classifiedImages.getImages()[0].getClassifiers()[0]
.getClasses()[0]
.className);
// print("${image.toString()}");
// print('ACCESS'+options.accessToken);
//print(options);
//print("${image.path}");
//print('CLASSIFICATION'+classifiedImages.customClasses.toString()); // StreamBuilder(
// stream: StreamMyClassifier(
// image,
// 'NRDjngCby2d-pSHOPyWQJxhuB6vOY2uOTCX6KV2BCfwB', 'CompostxLandfillxRecycle_2056123069'),
// builder: (context, snapshot) {
// if (snapshot.hasData) {
// _text = snapshot.data;
// print(_text);
// }
// else {
// print('NO DATA AVAILABLE');
// }
//
// }
// );
}
#override
Widget build(BuildContext context) {
return Scaffold(body:Stack(children:[Center(child:image==null?Image.file(File(imagePath)):Image.file(image)),Positioned(
top: MediaQuery.of(context).size.height/2,
child: FloatingActionButton(onPressed:() async{
await visualImageClassifier(image==null?File(imagePath):image);
},
child:Icon(Icons.arrow_right)),
)]));
}
}
The image is successfully displayed on my screen but once I send it through the visualRecognition.classifyImageFile(....); it gives me an error saying I can not use image because it only supports String. I converted it to String but it gives me the error below.
[ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: FileSystemException: Cannot retrieve length of file, path = 'File: '/data/user/0/com.example.ourearth2020/cache2020-09-17 18:50:16.530957.png'' (OS Error: No such file or directory, errno = 2)
E/flutter (17606): #0 _File.length.<anonymous closure> (dart:io/file_impl.dart:366:9)
E/flutter (17606): #1 _rootRunUnary (dart:async/zone.dart:1198:47)
E/flutter (17606): #2 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (17606): #3 _FutureListener.handleValue (dart:async/future_impl.dart:143:18)
E/flutter (17606): #4 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)
E/flutter (17606): #5 Future._propagateToListeners (dart:async/future_impl.dart:725:32)
E/flutter (17606): #6 Future._completeWithValue (dart:async/future_impl.dart:529:5)
E/flutter (17606): #7 Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:567:7)
E/flutter (17606): #8 _rootRun (dart:async/zone.dart:1190:13)
E/flutter (17606): #9 _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter (17606): #10 _CustomZone.runGuarded (dart:async/zone.dart:997:7)
E/flutter (17606): #11 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1037:23)
E/flutter (17606): #12 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (17606): #13 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
E/flutter (17606):
Some of the questions I have: Can I get the confidence score using this? The last time I tried using those statements to classify the image it used a general classifier(if I input an image of a skyscraper it told me skyscraper) so how can I have it classify with my 3 classifiers?
Btw I already set up the IBM Cloud and it is fully functional. The library that I found from pub.dev is here https://pub.dev/packages/flutter_ibm_watson
EDIT error code for getImages() method
[ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: NoSuchMethodError: The method 'getImages' was called on null.
E/flutter (31403): Receiver: null
E/flutter (31403): Tried calling: getImages()
E/flutter (31403): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
E/flutter (31403): #1 DisplayPicture.visualImageClassifier (package:ourearth2020/screens/VisualPage.dart:147:30)
E/flutter (31403): <asynchronous suspension>
E/flutter (31403): #2 DisplayPicture.build.<anonymous closure> (package:ourearth2020/screens/VisualPage.dart:177:15)
E/flutter (31403): #3 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:992:19)
E/flutter (31403): #4 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:1098:38)
E/flutter (31403): #5 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:184:24)
E/flutter (31403): #6 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:524:11)
E/flutter (31403): #7 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:284:5)
E/flutter (31403): #8 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:219:7)
E/flutter (31403): #9 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:477:9)
E/flutter (31403): #10 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:78:12)
E/flutter (31403): #11 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:124:9)
E/flutter (31403): #12 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:377:8)
E/flutter (31403): #13 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:122:18)
E/flutter (31403): #14 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:108:7)
E/flutter (31403): #15 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:220:19)
E/flutter (31403): #16 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:200:22)
E/flutter (31403): #17 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:158:7)
E/flutter (31403): #18 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:104:7)
E/flutter (31403): #19 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:88:7)
E/flutter (31403): #20 _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter (31403): #21 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (31403): #22 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (31403): #23 _invoke1 (dart:ui/hooks.dart:283:10)
E/flutter (31403): #24 _dispatchPointerDataPacket (dart:ui/hooks.dart:192:5)
E/flutter (31403):
You can copy past run full code below
You can see confidence score in working demo below
please change image.toString() to image.path because image is File
from
ClassifiedImages classifiedImages = await visualRecognition.classifyImageFile(image.toString());
to
ClassifiedImages classifiedImages = await visualRecognition.classifyImageFile(image.path);
working demo
working demo 2 for CameraPreview
I/flutter (31132): living room
full code
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter_ibm_watson/flutter_ibm_watson.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
class VisualPage extends StatefulWidget {
#override
_VisualPageState createState() => _VisualPageState();
}
class _VisualPageState extends State<VisualPage> {
CameraController _controller;
List cameras;
String path;
var galleryImage;
CameraDescription cameraDescription;
Future initCamera() async {
cameras = await availableCameras();
var frontCamera = cameras.first;
_controller = CameraController(frontCamera, ResolutionPreset.high);
try {
await _controller.initialize();
} catch (e) {}
print('Controller Is Init:' + _controller.value.isInitialized.toString());
displayPreview();
setState(() {});
}
bool displayPreview() {
if (_controller == null || !_controller.value.isInitialized) {
return false;
} else {
return true;
}
}
Future getImageFromGallery() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
galleryImage = image;
});
print('GALLERY IMAGE' + galleryImage.toString());
return galleryImage;
}
#override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
#override
void initState() {
super.initState();
print('Running');
initCamera();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Stack(children: [
displayPreview()
? AspectRatio(
aspectRatio: MediaQuery.of(context).size.width /
MediaQuery.of(context).size.height,
child: CameraPreview(_controller),
)
: Container(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.yellow),
),
),
Positioned(
top: MediaQuery.of(context).size.height - 120,
child: GestureDetector(
onTap: () async {
await getImageFromGallery();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
DisplayPicture(image: galleryImage)));
},
child: Icon(
Icons.image,
color: Colors.white,
size: 60,
)),
),
Positioned(
top: MediaQuery.of(context).size.height - 120,
left: MediaQuery.of(context).size.width / 2.2,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
child: Container(
child: Icon(
Icons.camera,
color: Colors.white,
size: 60,
)),
onTap: () async {
final path = (await getTemporaryDirectory()).path +
'${DateTime.now()}.png';
try {
await _controller.takePicture(path);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
DisplayPicture(imagePath: path)));
} catch (e) {
print('EEEE' + e);
}
}))
]));
}
}
class DisplayPicture extends StatelessWidget {
String imagePath;
File image;
String _text;
// File file = File(imagePath)
DisplayPicture({this.imagePath, this.image});
visualImageClassifier(File image) async {
IamOptions options = await IamOptions(
iamApiKey: "NRDjngCby2d-pSHOPyWQJxhuB6vOY2uOTCX6KV2BCfwB",
url:
"https://api.us-south.visual-recognition.watson.cloud.ibm.com/instances/ef286f4e-84c7-44e0-b63d-a6a49a142a30")
.build();
VisualRecognition visualRecognition = new VisualRecognition(
iamOptions: options,
language: Language.ENGLISH); // Language.ENGLISH is language response
ClassifiedImages classifiedImages =
await visualRecognition.classifyImageFile(image.path);
print(classifiedImages
.getImages()[0]
.getClassifiers()[0]
.getClasses()[0]
.className);
// print("${image.toString()}");
// print('ACCESS'+options.accessToken);
//print(options);
//print("${image.path}");
//print('CLASSIFICATION'+classifiedImages.customClasses.toString()); // StreamBuilder(
// stream: StreamMyClassifier(
// image,
// 'NRDjngCby2d-pSHOPyWQJxhuB6vOY2uOTCX6KV2BCfwB', 'CompostxLandfillxRecycle_2056123069'),
// builder: (context, snapshot) {
// if (snapshot.hasData) {
// _text = snapshot.data;
// print(_text);
// }
// else {
// print('NO DATA AVAILABLE');
// }
//
// }
// );
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: [
Center(
child:
image == null ? Image.file(File(imagePath)) : Image.file(image)),
Positioned(
top: MediaQuery.of(context).size.height / 2,
child: FloatingActionButton(
onPressed: () async {
await visualImageClassifier(
image == null ? File(imagePath) : image);
},
child: Icon(Icons.arrow_right)),
)
]));
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: VisualPage(),
);
}
}
I have a test where I'm trying to observe the behaviour of the [Navigator] when the app navigates from contacts_footer.dart to create_and_edit_contact.dart (push) and back (pop). Using verify from the Mockito package, I can successfully verify that the push behaviour works however, verifying the pop behaviour fails. The function _navigateToBack works as expected and testing for widgets that appear only in the contacts_footer.dart is successful, but observing the pop behaviour fails.
contacts_footer.dart
class ContactsFooter extends StatelessWidget {
static const navigateToEditPage = Key('navigateEdit');
const ContactsFooter({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return BottomAppBar(
color: Color.fromRGBO(244, 244, 244, 1),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(Icons.edit),
onPressed: () {
Provider.of<Contacts>(context).setEditMode(true);
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => CreateAndEditContact()));
},
key: ContactsFooter.navigateToEditPage,
)
],
),
);
}
}
create_and_edit_contact.dart
class CreateAndEditContact extends StatefulWidget {
static const routeName = 'edit-contact';
static var editOrCreateDetails = Key('editOrCreate');
#override
_CreateAndEditContactState createState() => _CreateAndEditContactState();
}
class _CreateAndEditContactState extends State<CreateAndEditContact> {
...
Widget build(BuildContext context) {
_isEditMode = Provider.of<Contacts>(context).isEditMode;
...
return Scaffold (
..
RaisedButton(key: CreateAndEditContact.editOrCreateDetails,
onPressed: () {
....
if (_isEditMode) {
print(true);
Provider.of<Contacts>(context)
.updateContact(context,formData, _selectedContact.vUuid)
.then((data) {
Navigator.of(context).pop();
});
} else {
print(false);
Provider.of<Contacts>(context)
.createContact(context,formData)
.then((data) {
Navigator.of(context).pop();
}).catchError(
(error) => showDialog(
context: context,
builder: (context) => ErrorDialog(
error.toString(),
),
),
);
}
},
child: Text(
'Sumbit',
style: TextStyle(color: Colors.white),
),
color: Theme.of(context).accentColor,
),
)
}
}
test file .
group('EditPage navigation tests', () {
NavigatorObserver mockObserver;
setUp(() {
mockObserver = MockNavigatorObserver();
});
Future<Null> _buildMainPage(WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Builder(
builder: (context) => Center(
child: MultiProvider(
providers: [
ChangeNotifierProvider<Contacts>(create: (_) => Contacts()),
],
child: Builder(
builder: (_) => MaterialApp(home: ContactsFooter(),
),
);,
),
),
),
/// This mocked observer will now receive all navigation events
/// that happen in our app.
navigatorObservers: <NavigatorObserver>[mockObserver],
));
/// The tester.pumpWidget() call above just built our app widget
/// and triggered the pushObserver method on the mockObserver once.
}
Future<Null> _navigateToDetailsPage(WidgetTester tester) async {
/// Tap the button which should navigate to the edit details page.
/// By calling tester.pumpAndSettle(), we ensure that all animations
/// have completed before we continue further.
await tester.tap(find.byKey(ContactsFooter.navigateToEditPage));
await tester.pumpAndSettle();
}
Future<Null> _navigateToBack(WidgetTester tester) async {
await tester.tap(find.byKey(CreateAndEditContact.editOrCreateDetails));
int num = await tester.pumpAndSettle();
print(num);
}
testWidgets(
'when tapping "navigate to edit details" button, should navigate to details page',
(WidgetTester tester) async {
await _buildMainPage(tester);
//CreateAndEditContact widget not present on screen as push event is not triggered yet
expect(find.byType(CreateAndEditContact), findsNothing);
//Trigger push event
await _navigateToDetailsPage(tester);
// By tapping the button, we should've now navigated to the edit details
// page. The didPush() method should've been called...
final Route pushedRoute =
verify(mockObserver.didPush(captureAny, any)).captured.single;
print(pushedRoute);
// there should be a CreateAndEditContact page present in the widget tree...
var createAndEdit = find.byType(CreateAndEditContact);
expect(createAndEdit, findsOneWidget);
await _navigateToBack(tester);
verify(mockObserver.didPop(any, any));
expect(find.byType(CreateAndEditContact), findsNothing);
expect(find.byKey(ContactsFooter.navigateToEditPage), findsWidgets);
});
}
All the expect statements execute correctly. However verify(mockObserver.didPop(any, any)); results in an exception as if [NavigatorObserver] did not recognize the pop behaviour.
>(RouteSettings("/", null), animation: AnimationController#1a3c6(⏭ 1.000; paused; for MaterialPageRoute<dynamic>(/)))
5
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
No matching calls. All calls: MockNavigatorObserver.navigator,
MockNavigatorObserver._navigator==NavigatorState#36772(tickers: tracking 1 ticker), [VERIFIED]
MockNavigatorObserver.didPush(MaterialPageRoute<dynamic>(RouteSettings("/", null), animation:
AnimationController#1a3c6(⏭ 1.000; paused; for MaterialPageRoute<dynamic>(/))), null)
(If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.)
When the exception was thrown, this was the stack:
#0 fail (package:test_api/src/frontend/expect.dart:153:30)
#1 _VerifyCall._checkWith (package:mockito/src/mock.dart:648:7)
#2 _makeVerify.<anonymous closure> (package:mockito/src/mock.dart:935:18)
#3 main.<anonymous closure>.<anonymous closure> (file:///Users/calvin.gonsalves/Projects/Flutter/Dec23-2019/cmic_mobile_field/test/main_widget_test.dart:316:13)
<asynchronous suspension>
#4 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:124:25)
#5 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:696:19)
<asynchronous suspension>
#8 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:679:14)
#9 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1050:24)
#15 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1047:15)
#16 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:121:22)
#17 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:171:27)
<asynchronous suspension>
#18 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:242:15)
#23 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:239:5)
#24 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:33)
#29 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:13)
#30 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:392:25)
#44 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:384:19)
#45 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:418:5)
#46 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)
(elided 28 frames from class _FakeAsync, package dart:async, package dart:async-patch, and package stack_trace)
The test description was:
when tapping "navigate to edit details" button, should navigate to details page
════════════════════════════════════════════════════════════════════════════════════════════════════
Test failed. See exception logs above.
The test description was: when tapping "navigate to edit details" button, should navigate to details page
✖ EditPage navigation tests when tapping "navigate to edit details" button, should navigate to details page
I referred https://iirokrankka.com/2018/08/22/writing-widget-tests-for-navigation-events/
The issue seems to be caused by Navigator lacking context - usually provided by MaterialApp in this case. As you've mentioned in the comments, moving navigatorObservers inside MaterialApp solves the issue. Another workaround is to use navigatorKey to directly manage Navigator without obtaining it first from a BuildContext. See this similar Stack Overflow post on how you can utilize navigatorKey.
I created an animation using Flare for my Flutter project. But, I got an error when trying to Run it. The animation doesn't work and only a black screen with the logo i used shows.
Here is my code:
import 'package:flare_splash_screen/flare_splash_screen.dart';
import 'package:flutter/material.dart';
void main () {
runApp(MaterialApp(
home: SplashScreen(
'assets/splash.flr',
(context) => SplashTela(),
startAnimation: 'intro',
backgroundColor: Color(0xff3333),
),
));
}
class SplashTela extends StatefulWidget {
#override
_SplashTelaState createState() => _SplashTelaState();
}
class _SplashTelaState extends State<SplashTela> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: Container(
color: Colors.redAccent,
),
);
}
}
And here is the error:
E/flutter (25496): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception:
'package:flare_splash_screen/flare_splash_screen.dart': Failed assertion: line 113 pos 16: '!
(isLoading == null && until == null)': isLoading and until are null, pick one ;)
E/flutter (25496): #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:40:39)
E/flutter (25496): #1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5)
E/flutter (25496): #2 new SplashScreen
(package:flare_splash_screen/flare_splash_screen.dart:113:16)
E/flutter (25496): #3 main (package:leagueuniverse/main.dart:6:11)
E/flutter (25496): #4 _runMainZoned.<anonymous closure>.<anonymous closure>
(dart:ui/hooks.dart:229:25)
E/flutter (25496): #5 _rootRun (dart:async/zone.dart:1124:13)
E/flutter (25496): #6 _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter (25496): #7 _runZoned (dart:async/zone.dart:1516:10)
E/flutter (25496): #8 runZoned (dart:async/zone.dart:1500:12)
E/flutter (25496): #9 _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:221:5)
E/flutter (25496): #10 _startIsolate.<anonymous closure> (dart:isolate-
patch/isolate_patch.dart:305:19)
E/flutter (25496): #11 _RawReceivePortImpl._handleMessage (dart:isolate-
patch/isolate_patch.dart:172:12)
E/flutter (25496):
you need to pass until: () => Future.delayed(Duration(seconds: 5)),
or use isLoading demo code for isLoading https://github.com/jaumard/flare_splash_screen/blob/master/example/lib/isLoading.dart
an use SplashScreen.navigate
I use official example to test your case
code snippet
void main() {
runApp(MaterialApp(
home: SplashScreen.navigate(
name: 'assets/intro.flr',
next: (context) => SplashTela(),
startAnimation: '1',
backgroundColor: Color(0xff3333),
until: () => Future.delayed(Duration(seconds: 5)),
),
));
}
full test code work without error
import 'package:flare_splash_screen/flare_splash_screen.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: SplashScreen.navigate(
name: 'assets/intro.flr',
next: (context) => SplashTela(),
startAnimation: '1',
backgroundColor: Color(0xff3333),
until: () => Future.delayed(Duration(seconds: 5)),
),
));
}
class SplashTela extends StatefulWidget {
#override
_SplashTelaState createState() => _SplashTelaState();
}
class _SplashTelaState extends State<SplashTela> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: Container(
color: Colors.redAccent,
),
);
}
}
Is there an example on how to create a draw app & reuse widgets occupying the screen? Yes I know there is an example in the gallery demo app. However that's a bit cheeky because that sample doesn't actually replace, set or change route to a different widget.
I've tried a the new instance of a widget from the onTap event of the drawer item. I've tried having my Getting duplicate global key errors when creating new instances of those widgets when an item is selected from the drawer and the old/new route is pop/pushed
ScheduleHomeWidget scheduleWidget = new ScheduleHomeWidget(onSendFeedback: widget.onSendFeedback,);
SpeakerListWidget speakerWidget = new SpeakerListWidget();
var routes = <String, WidgetBuilder> {
ScheduleHomeWidget.routeName : (BuildContext context) => scheduleWidget,
SpeakerListWidget.routeName : (BuildContext context) => speakerWidget
};
and my MaterialApp:
return new MaterialApp(
title: kAppTitle,
routes: routes,
home: scheduleWidget,
);
and the code to launch the new route:
onTap: () {
if (routeName != null) {
Timeline.instantSync('Start Transition', arguments: <String, String>{
'from': '/',
'to': routeName
});
Navigator.pop(context);
Navigator.pushNamed(context, routeName);
}
}
}
I'm not specifying a key when instantiating either the ScheduleHomeWidget or the SpeakerListWidget instantiation. That said, the ScheduleHomeWidget uses an AnimatedList which does use a GlobalKey<AnimatedListState>
I'll see the following exception:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building Flexible(flex: 1):
Multiple widgets used the same GlobalKey.
The key [LabeledGlobalKey<AnimatedListState>#d63d7] was used by multiple widgets. The parents of
those widgets were different widgets that both had the following description:
Flexible(flex: 1)
A GlobalKey can only be specified on one widget at a time in the widget tree.
When the exception was thrown, this was the stack:
#0 GlobalKey._debugReserveFor.<anonymous closure> (package:flutter/src/widgets/framework.dart:238:9)
#2 GlobalKey._debugReserveFor (package:flutter/src/widgets/framework.dart:219:12)
#3 Element.updateChild.<anonymous closure> (package:flutter/src/widgets/framework.dart:2524:13)
#5 Element.updateChild (package:flutter/src/widgets/framework.dart:2521:12)
#6 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#7 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#8 ProxyElement.update (package:flutter/src/widgets/framework.dart:3639:5)
#9 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#10 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:4066:32)
#11 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4448:17)
#12 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#13 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#14 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#15 ProxyElement.update (package:flutter/src/widgets/framework.dart:3639:5)
#16 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#17 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:4066:32)
#18 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4448:17)
#19 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#20 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#21 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#22 ProxyElement.update (package:flutter/src/widgets/framework.dart:3639:5)
#23 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#24 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#25 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#26 StatefulElement.update (package:flutter/src/widgets/framework.dart:3528:5)
#27 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#28 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4340:14)
#29 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#30 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#31 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#32 StatelessElement.update (package:flutter/src/widgets/framework.dart:3453:5)
#33 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#34 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4340:14)
#35 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#36 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#37 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#38 StatefulElement.update (package:flutter/src/widgets/framework.dart:3528:5)
#39 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#40 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#41 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#42 StatefulElement.update (package:flutter/src/widgets/framework.dart:3528:5)
#43 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#44 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#45 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#46 ProxyElement.update (package:flutter/src/widgets/framework.dart:3639:5)
#47 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#48 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#49 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#50 ProxyElement.update (package:flutter/src/widgets/framework.dart:3639:5)
#51 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#52 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#53 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#54 StatefulElement.update (package:flutter/src/widgets/framework.dart:3528:5)
#55 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#56 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#57 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#58 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2142:33)
#59 BindingBase&SchedulerBinding&GestureBinding&ServicesBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:503:20)
#60 BindingBase&SchedulerBinding&GestureBinding&ServicesBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:189:5)
#61 BindingBase&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:688:15)
#62 BindingBase&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:636:9)
#63 BindingBase&SchedulerBinding&GestureBinding&ServicesBinding&RendererBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/rendering/binding.dart:275:20)
#65 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:366)
#66 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:394)
#67 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
(elided 3 frames from class _AssertionError and package dart:async-patch)
════════════════════════════════════════════════════════════════════════════════════════════════════
Reloaded 9 of 459 libraries in 2,143ms.
Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3727 pos 14: '_dependents.isEmpty': is not true.
Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 1662 pos 12: '_elements.contains(element)': is not true.`
This error looks like Flutter is trying to add a widget to the tree by it's ID more than once. Not really trying to do that. Just looking to have two widgets that can take the main focus of the screen. Don't necessarily have to be created a new each time a user selects from the side bar.
What you can do here is add a Navigator on home. With this setup, you can manage the navigation with a Navigator key.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
drawer: Drawer(
child: ListView(
children: _drawer(),
),
),
body: Navigator(
key: _navigatorKey, // use a Navigator key so the app won't be confused when managing routes
initialRoute: Nemo.pageA, // Set default page
...
),
);
}
The Navigator returns the Widget builder of the selected tab.
Navigator(
key: _navigatorKey, // use a Navigator key so the app won't be confused when managing routes
initialRoute: Nemo.pageA, // Set default page
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
_currentPage = settings.name;
// Depending on the route name pushed
// set the Widget builder to be returned by the Navigator
// if pushed route is non-existent, return a 404 page
switch (settings.name) {
case Nemo.pageA:
builder = (BuildContext context) => const Center(child: Text('Page A'));
break;
case Nemo.pageB:
builder = (BuildContext context) => const Center(child: Text('Page B'));
break;
case Nemo.pageC:
builder = (BuildContext context) => const Center(child: Text('Page C'));
break;
default:
builder = (BuildContext context) => const Center(child: Text('404'));
}
return MaterialPageRoute(
builder: builder,
settings: settings,
);
},
),
On your drawer, you can push the route when the tab has been tapped. Check if the tab tapped is the current page displayed on screen so the same page won't be pushed by the Navigator again.
List<Widget> _drawer() {
return <Widget>[
ListTile(
title: const Text('Page A'),
onTap: () {
Navigator.pop(context);
if (_currentPage != Nemo.pageA) {
_navigatorKey.currentState!
.pushNamedAndRemoveUntil(Nemo.pageA, (Route route) => false);
}
},
),
...
];
}
Complete sample
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class Nemo {
static const String pageA = '/pageA';
static const String pageB = '/pageB';
static const String pageC = '/pageC';
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _navigatorKey = GlobalKey<NavigatorState>();
String? _currentPage;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
drawer: Drawer(
child: ListView(
children: _drawer(),
),
),
body: Navigator(
key:
_navigatorKey, // use a Navigator key so the app won't be confused when managing routes
initialRoute: Nemo.pageA, // Set default page
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
_currentPage = settings.name;
// Depending on the route name pushed
// set the Widget builder to be returned by the Navigator
// if pushed route is non-existent, return a 404 page
switch (settings.name) {
case Nemo.pageA:
builder =
(BuildContext context) => const Center(child: Text('Page A'));
break;
case Nemo.pageB:
builder =
(BuildContext context) => const Center(child: Text('Page B'));
break;
case Nemo.pageC:
builder =
(BuildContext context) => const Center(child: Text('Page C'));
break;
default:
builder =
(BuildContext context) => const Center(child: Text('404'));
}
return MaterialPageRoute(
builder: builder,
settings: settings,
);
},
),
);
}
List<Widget> _drawer() {
return <Widget>[
ListTile(
title: const Text('Page A'),
onTap: () {
Navigator.pop(context);
if (_currentPage != Nemo.pageA) {
_navigatorKey.currentState!
.pushNamedAndRemoveUntil(Nemo.pageA, (Route route) => false);
}
},
),
ListTile(
title: const Text('Page B'),
onTap: () {
Navigator.pop(context);
if (_currentPage != Nemo.pageB) {
_navigatorKey.currentState!
.pushNamedAndRemoveUntil(Nemo.pageB, (Route route) => false);
}
},
),
ListTile(
title: const Text('Page C'),
onTap: () {
Navigator.pop(context);
if (_currentPage != Nemo.pageC) {
_navigatorKey.currentState!
.pushNamedAndRemoveUntil(Nemo.pageC, (Route route) => false);
}
},
),
];
}
}