I need to pass a function from one stateful widget to another.
Parent widget::
the function that I am passing is the following
void _setJobAddress(jobAddress) {
setState(() {
_jobAddress = jobAddress;
});
}
here is the button that opens the new view, this is how I am passing the function
TextButton(
onPressed: () => {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
SearchLocationScreen(_setJobAddress)))
}
this is a little bit of the child view where I need to call the function::
class SearchLocationScreen extends StatefulWidget {
const SearchLocationScreen({Key? key}) : super(key: key);
#override
State<SearchLocationScreen> createState() => _SearchLocationScreenState();
}
class _SearchLocationScreenState extends State<SearchLocationScreen> {
Function setJobAddess; // i tried adding this, but its not working
_SearchLocationScreenState(this.setJobAddess); // i tried adding this, but its not working
List<AutocompletePrediction> placePredictions = [];
How can I make this work so that when I click a button on the child widget, the parent function passed is called?
I tried the following:
class SearchLocationScreen extends StatefulWidget {
const SearchLocationScreen(
this.setJobAddess, {
Key? key,
}) : super(key: key);
final setJobAddess;
#override
State<SearchLocationScreen> createState() => _SearchLocationScreenState();
}
class _SearchLocationScreenState extends State<SearchLocationScreen> {
//Function setJobAddess;
//_SearchLocationScreenState(this.setJobAddess);
List<AutocompletePrediction> placePredictions = [];
#override
void initState() {
widget.setJobAddess();
}
... a bunch of code that is not of importance goes here
Padding(
padding: const EdgeInsets.all(defaultPadding),
child: ElevatedButton.icon(
onPressed: () async {
print('setting job location');
widget.setJobAddess('TEXT');
Navigator.pop(context);
},
icon: Icon(Icons.home),
label: const Text("Set job location"),
style: ElevatedButton.styleFrom(
backgroundColor: secondaryColor10LightTheme,
foregroundColor: textColorLightTheme,
elevation: 0,
fixedSize: const Size(double.infinity, 40),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
),
),
),
I got the following error::
════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building Builder:
Closure call with mismatched arguments: function '_CreateUpdateJobViewState._setJobAddress'
Receiver: Closure: (dynamic) => void from Function '_setJobAddress#43263735':.
Tried calling: _CreateUpdateJobViewState._setJobAddress()
Found: _CreateUpdateJobViewState._setJobAddress(dynamic) => void
The relevant error-causing widget was
MaterialApp
lib/main.dart:20
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:38:5)
#1 _objectNoSuchMethod (dart:core-patch/object_patch.dart:85:9)
#2 _SearchLocationScreenState.initState
package:ijob_clone_app/…/location/location_search_screen.dart:26
#3 StatefulElement._firstBuild
package:flutter/…/widgets/framework.dart:5015
#4 ComponentElement.mount
package:flutter/…/widgets/framework.dart:4853
... Normal element mounting (275 frames)
#279 Element.inflateWidget
package:flutter/…/widgets/framework.dart:3863
#280 MultiChildRenderObjectElement.inflateWidget
package:flutter/…/widgets/framework.dart:6435
#281 Element.updateChild
package:flutter/…/widgets/framework.dart:3592
#282 RenderObjectElement.updateChildren
package:flutter/…/widgets/framework.dart:5964
#283 MultiChildRenderObjectElement.update
package:flutter/…/widgets/framework.dart:6460
#284 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#285 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#286 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:5050
#287 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#288 StatefulElement.update
package:flutter/…/widgets/framework.dart:5082
#289 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#290 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#291 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#292 ProxyElement.update
package:flutter/…/widgets/framework.dart:5228
#293 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#294 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#295 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#296 ProxyElement.update
package:flutter/…/widgets/framework.dart:5228
#297 _InheritedNotifierElement.update
package:flutter/…/widgets/inherited_notifier.dart:107
#298 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#299 SingleChildRenderObjectElement.update
package:flutter/…/widgets/framework.dart:6307
#300 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#301 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#302 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:5050
#303 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#304 StatefulElement.update
package:flutter/…/widgets/framework.dart:5082
#305 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#306 SingleChildRenderObjectElement.update
package:flutter/…/widgets/framework.dart:6307
#307 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#308 SingleChildRenderObjectElement.update
package:flutter/…/widgets/framework.dart:6307
#309 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#310 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#311 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#312 ProxyElement.update
package:flutter/…/widgets/framework.dart:5228
#313 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#314 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#315 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:5050
#316 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#317 BuildOwner.buildScope
package:flutter/…/widgets/framework.dart:2667
#318 WidgetsBinding.drawFrame
package:flutter/…/widgets/binding.dart:882
#319 RendererBinding._handlePersistentFrameCallback
package:flutter/…/rendering/binding.dart:378
#320 SchedulerBinding._invokeFrameCallback
package:flutter/…/scheduler/binding.dart:1175
#321 SchedulerBinding.handleDrawFrame
package:flutter/…/scheduler/binding.dart:1104
#322 SchedulerBinding._handleDrawFrame
package:flutter/…/scheduler/binding.dart:1015
#323 _invoke (dart:ui/hooks.dart:148:13)
#324 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#325 _drawFrame (dart:ui/hooks.dart:115:31)
════════════════════════════════════════════════════════════════════════════════
D/EGL_emulation(15747): app_time_stats: avg=25.04ms min=14.73ms max=497.29ms count=59
D/TrafficStats(15747): tagSocket(145) with statsTag=0xffffffff, statsUid=-1
D/TrafficStats(15747): tagSocket(121) with statsTag=0xffffffff, statsUid=-1
with this you can pass it and get it from the constructor.
class SearchLocationScreen extends StatefulWidget {
const SearchLocationScreen(this.setJobAddess,{Key? key, }) : super(key: key);
final setJobAddess;
#override
State<SearchLocationScreen> createState() => _SearchLocationScreenState();
}
class _SearchLocationScreenState extends State<SearchLocationScreen> {
/*now you can use call it with like this */
#override
void initState() {
widget.setJobAddess();
}
List<AutocompletePrediction> placePredictions = [];
// your other code
the StatefulWidget gives you the possibility to get properties from the constructor, and to access that property from the State class you need just to use widget.setJobAddess();
this is what worked for me
TextButton(
onPressed: () => {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SearchLocationScreen(
setJobAddress: _setJobAddress)))
},
child: Text(_jobAddress),
),
child widget::
class SearchLocationScreen extends StatefulWidget {
final Function setJobAddress;
const SearchLocationScreen({Key? key, required this.setJobAddress})
: super(key: key);
#override
State<SearchLocationScreen> createState() => _SearchLocationScreenState();
}
class _SearchLocationScreenState extends State<SearchLocationScreen> {
List<AutocompletePrediction> placePredictions = [];
#override
...
Expanded(
child: ListView.builder(
itemCount: placePredictions.length,
itemBuilder: ((context, index) => LocationListTile(
press: () {
widget
.setJobAddress(placePredictions[index].description);
Navigator.pop(context);
},
location: placePredictions[index].description!,
))),
),
Related
I am using Riverpod (package:flutter_riverpod v1.0.3) to manage state in my Flutter app. I would like to have a list of Widgets built based on the items in a model. Each list item Widget uses provider.select to pick the corresponding model item at its index. See the following example app:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(const MyApp());
}
final provider = StateNotifierProvider<FruitStateNotifier, List<String>>((ref) {
return FruitStateNotifier(['apricot', 'blueberry', 'cherry']);
});
class FruitStateNotifier extends StateNotifier<List<String>> {
FruitStateNotifier(List<String> fruits) : super(fruits);
void update(List<String> fruits) => state = fruits;
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const ProviderScope(
child: MaterialApp(
home: Scaffold(
body: FruitList(),
),
),
);
}
}
class FruitList extends ConsumerWidget {
const FruitList({Key? key}) : super(key: key);
#override
Widget build(BuildContext context, WidgetRef ref) {
return ListView.builder(
itemCount: ref.watch(provider.select((p) => p.length)),
itemBuilder: (context, index) {
return ListTile(
title: Text('$index) ${ref.watch(provider.select((p) => p[index]))}'),
trailing: IconButton(
onPressed: () {
final fruits = ref.read(provider);
final newFruits = List.of(fruits)..removeAt(index);
ref.read(provider.notifier).update(newFruits);
},
icon: const Icon(Icons.delete),
),
);
},
);
}
}
However, when deleting an element, the select functions are run, but it seems that the ListView's item count has not yet been updated to match the model's item count. This causes the last Widget in the list to have no corresponding model item, and so we get an error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: An exception was thrown while building StateNotifierProvider<FruitStateNotifier, List<String>>#82be7.
Thrown exception:
RangeError (index): Invalid value: Not in inclusive range 0..1: 2
Stack trace:
#0 List.[] (dart:core-patch/growable_array.dart:281:36)
#1 FruitList.build.<anonymous closure>.<anonymous closure>
#2 _ProviderSelector._select.<anonymous closure>
#3 ResultData.map
#4 _ProviderSelector._select
#5 _ProviderSelector._selectOnChange
#6 _ProviderSelector.listen.<anonymous closure>
#7 _rootRunBinary (dart:async/zone.dart:1450:47)
#8 _CustomZone.runBinary (dart:async/zone.dart:1342:19)
#9 _CustomZone.runBinaryGuarded (dart:async/zone.dart:1252:7)
#10 ProviderElementBase._notifyListeners.<anonymous closure>
#11 ResultData.map
#12 ProviderElementBase._notifyListeners
#13 ProviderElementBase.setState
#14 StateNotifierProvider.create.listener
#15 StateNotifier.state=
#16 FruitStateNotifier.update
#17 FruitList.build.<anonymous closure>.<anonymous closure>
#18 _InkResponseState._handleTap
#19 GestureRecognizer.invokeCallback
#20 TapGestureRecognizer.handleTapUp
#21 BaseTapGestureRecognizer._checkUp
#22 BaseTapGestureRecognizer.handlePrimaryPointer
#23 PrimaryPointerGestureRecognizer.handleEvent
#24 PointerRouter._dispatch
#25 PointerRouter._dispatchEventToRoutes.<anonymous closure>
#26 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:539:8)
#27 PointerRouter._dispatchEventToRoutes
#28 PointerRouter.route
#29 GestureBinding.handleEvent
#30 GestureBinding.dispatchEvent
#31 RendererBinding.dispatchEvent
#32 GestureBinding._handlePointerEventImmediately
#33 GestureBinding.handlePointerEvent
#34 GestureBinding._flushPointerEventQueue
#35 GestureBinding._handlePointerDataPacket
#36 _rootRunUnary (dart:async/zone.dart:1442:13)
#37 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#38 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#39 _invoke1 (dart:ui/hooks.dart:170:10)
#40 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:331:7)
#41 _dispatchPointerDataPacket (dart:ui/hooks.dart:94:31)
#0 _fallbackOnErrorForProvider
#1 _ProviderSelector.listen
#2 ProviderContainer.listen
#3 ConsumerStatefulElement.watch.<anonymous closure>
#4 _LinkedHashMapMixin.putIfAbsent (dart:collection-patch/compact_hash.dart:453:23)
#5 ConsumerStatefulElement.watch
#6 FruitList.build.<anonymous closure>
#7 SliverChildBuilderDelegate.build
#8 SliverMultiBoxAdaptorElement._build
#9 SliverMultiBoxAdaptorElement.createChild.<anonymous closure>
#10 BuildOwner.buildScope
#11 SliverMultiBoxAdaptorElement.createChild
#12 RenderSliverMultiBoxAdaptor._createOrObtainChild.<anonymous closure>
#13 RenderObject.invokeLayoutCallback.<anonymous closure>
#14 PipelineOwner._enableMutationsToDirtySubtrees
#15 RenderObject.invokeLayoutCallback
#16 RenderSliverMultiBoxAdaptor._createOrObtainChild
#17 RenderSliverMultiBoxAdaptor.insertAndLayoutChild
#18 RenderSliverList.performLayout.advance
#19 RenderSliverList.performLayout
#20 RenderObject.layout
#21 RenderSliverEdgeInsetsPadding.performLayout
#22 RenderSliverPadding.performLayout
#23 RenderObject.layout
#24 RenderViewportBase.layoutChildSequence
#25 RenderViewport._attemptLayout
#26 RenderViewport.performLayout
#27 RenderObject.layout
#28 RenderProxyBoxMixin.performLayout
#29 RenderObject.layout
#30 RenderProxyBoxMixin.performLayout
#31 RenderObject.layout
#32 RenderProxyBoxMixin.performLayout
#33 RenderObject.layout
#34 RenderProxyBoxMixin.performLayout
#35 RenderObject.layout
#36 RenderProxyBoxMixin.performLayout
#37 RenderObject.layout
#38 RenderProxyBoxMixin.performLayout
#39 RenderObject.layout
#40 RenderProxyBoxMixin.performLayout
#41 RenderObject.layout
#42 RenderProxyBoxMixin.performLayout
#43 RenderCustomPaint.performLayout
#44 RenderObject.layout
#45 RenderProxyBoxMixin.performLayout
#46 RenderObject.layout
#47 RenderProxyBoxMixin.performLayout
#48 RenderObject.layout
#49 RenderProxyBoxMixin.performLayout
#50 RenderObject.layout
#51 RenderProxyBoxMixin.performLayout
#52 RenderObject.layout
#53 MultiChildLayoutDelegate.layoutChild
#54 _ScaffoldLayout.performLayout
#55 MultiChildLayoutDelegate._callPerformLayout
#56 RenderCustomMultiChildLayoutBox.performLayout
#57 RenderObject.layout
#58 RenderProxyBoxMixin.performLayout
#59 RenderObject.layout
#60 RenderProxyBoxMixin.performLayout
#61 _RenderCustomClip.performLayout
#62 RenderObject.layout
#63 RenderProxyBoxMixin.performLayout
#64 RenderObject.layout
#65 RenderProxyBoxMixin.performLayout
#66 RenderObject.layout
#67 RenderProxyBoxMixin.performLayout
#68 RenderObject.layout
#69 RenderProxyBoxMixin.performLayout
#70 RenderObject.layout
#71 RenderProxyBoxMixin.performLayout
#72 RenderObject.layout
#73 RenderProxyBoxMixin.performLayout
#74 RenderObject.layout
#75 RenderProxyBoxMixin.performLayout
#76 RenderObject.layout
#77 RenderProxyBoxMixin.performLayout
#78 RenderObject.layout
#79 RenderProxyBoxMixin.performLayout
#80 RenderOffstage.performLayout
#81 RenderObject.layout
#82 RenderProxyBoxMixin.performLayout
#83 RenderObject.layout
#84 _RenderTheatre.performLayout
#85 RenderObject.layout
#86 RenderProxyBoxMixin.performLayout
#87 RenderObject.layout
#88 RenderProxyBoxMixin.performLayout
#89 RenderObject.layout
#90 RenderProxyBoxMixin.performLayout
#91 RenderObject.layout
#92 RenderProxyBoxMixin.performLayout
#93 RenderCustomPaint.performLayout
#94 RenderObject.layout
#95 RenderProxyBoxMixin.performLayout
#96 RenderObject.layout
#97 RenderProxyBoxMixin.performLayout
#98 RenderObject.layout
#99 RenderProxyBoxMixin.performLayout
#100 RenderObject.layout
#101 RenderProxyBoxMixin.performLayout
#102 RenderObject.layout
#103 RenderView.performLayout
#104 RenderObject._layoutWithoutResize
#105 PipelineOwner.flushLayout
#106 RendererBinding.drawFrame
#107 WidgetsBinding.drawFrame
#108 RendererBinding._handlePersistentFrameCallback
#109 SchedulerBinding._invokeFrameCallback
#110 SchedulerBinding.handleDrawFrame
#111 SchedulerBinding.scheduleWarmUpFrame.<anonymous closure>
#112 _rootRun (dart:async/zone.dart:1418:47)
#113 _CustomZone.run (dart:async/zone.dart:1328:19)
#114 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
#115 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
#116 _rootRun (dart:async/zone.dart:1426:13)
#117 _CustomZone.run (dart:async/zone.dart:1328:19)
#118 _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1260:23)
#119 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
#120 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:395:19)
#121 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:426:5)
#122 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
How can I build the list and its children without this issue?
Using select here does not really make sense, you are not optimizing rebuilds, since it will be rebuilt when the number of items in the list changes anyway.
The best you can do here is just watch the state once and assign it to a variable:
final fruitList = ref.watch(provider);
Then just use the variable to get the length and build the list items.
So the resulting code will be:
class FruitList extends ConsumerWidget {
const FruitList({Key? key}) : super(key: key);
#override
Widget build(BuildContext context, WidgetRef ref) {
final fruitList = ref.watch(provider);
return ListView.builder(
itemCount: fruitList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('$index) ${fruitList[index]}'),
trailing: IconButton(
onPressed: () {
final newFruits = List.of(fruitList)..removeAt(index);
ref.read(provider.notifier).update(newFruits);
},
icon: const Icon(Icons.delete),
),
);
},
);
}
}
Try this:
class FruitList extends ConsumerWidget {
const FruitList({Key? key}) : super(key: key);
#override
Widget build(BuildContext context, WidgetRef ref) {
final list = ref.watch(provider);
return ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('$index) ${list[index]}'),
trailing: IconButton(
onPressed: () {
final fruits = ref.read(provider);
final newFruits = List.of(fruits)..removeAt(index);
ref.read(provider.notifier).update(newFruits);
},
icon: const Icon(Icons.delete),
),
);
},
);
}
}
I created a todo app using riverpod, so I used ref.watch(todoController.select((value) => value.length) to rebuild todo listView whenever todo list length changes, but for update I used ref.watch(todoController.select((value) => value[index]) to rebuild only that listTile whose item changes, it was working fine but when deleted any item was getting the invalid range error, so what i did is that in ListTile provider.select added a condition
todoController.select((value) => value.length > index ? value[index]: null),
and now not getting error on deleting, on update only listTile rebuild which needs to and on creating and delete whole listview rebuild w/o invalid range exception
class TodosListWidget extends ConsumerWidget {
const TodosListWidget({Key? key}) : super(key: key);
#override
Widget build(BuildContext context, WidgetRef ref) {
print('rebuild todo List');
final todosItem = ref.watch(todoController.select((value) => value.length));
return ListView.builder(
itemCount: todosItem,
itemBuilder: ((context, index) => TodoWidget(index: index,)
));
}
}
class TodoWidget extends ConsumerWidget {
final int index;
const TodoWidget({required this.index, Key? key}) : super(key: key);
#override
Widget build(BuildContext context, WidgetRef ref) {
final currentTodo =
ref.watch(todoController.select((value) => value.length > index ? value[index]: null));
print('rebuild Current todo');
return InkWell(
onDoubleTap: () => ref
.read(todoController.notifier)
.deleteTodo(currentTodo!.id),
onTap: () => ref
.read(todoController.notifier)
.updateTodo('change', 'todo is changed', currentTodo!.id),
child: ListTile(
title: Text(currentTodo!.name),
subtitle: Text(currentTodo.desc),
),
);
}
}
'package:flutter/src/widgets/scroll_controller.dart': Failed assertion: line 113 pos 12: '_positions.length == 1': ScrollController attached to multiple scroll views.
After that error bottom navigation bar stop changing the current page's of pageview.
PageController pageController;
class MainController extends StatefulWidget {
#override
_MainControllerState createState() => _MainControllerState();
}
class _MainControllerState extends State<MainController>
with TickerProviderStateMixin {
#override
void initState() {
// TODO: implement initState
super.initState();
pageController = PageController(initialPage: 0, keepPage: true);
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
pageController.dispose();
}
PagesList() {
return BlocBuilder<BottomnavbarcubitCubit, BottomnavbarcubitState>(
builder: (context, state) {
return Scaffold(
body: PageView(
allowImplicitScrolling: true,
controller: pageController,
onPageChanged: (int index) => state.currentIndex = index,
children: [
NotificationsScreen(),
NotificationsScreen(),
NotificationsScreen(),
NotificationsScreen(),
],
),
bottomNavigationBar: NormalNavBar(),
);
},
);
}
}
Bottomnavbar's onTap func that creates error
try {
if (pageController.hasClients)
await pageController.animateToPage(state.currentIndex,
duration: Duration(milliseconds: 500),
curve: Curves.elasticOut);
} catch (err) {
print(err);
}
E/flutter (30081): #18 GestureBinding._handlePointerEvent
package:flutter/…/gestures/binding.dart:295
E/flutter (30081): #19 GestureBinding._flushPointerEventQueue
package:flutter/…/gestures/binding.dart:240
E/flutter (30081): #20 GestureBinding._handlePointerDataPacket
package:flutter/…/gestures/binding.dart:213
E/flutter (30081): #21 _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter (30081): #22 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (30081): #23 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (30081): #24 _invoke1 (dart:ui/hooks.dart:265:10)
E/flutter (30081): #25 _dispatchPointerDataPacket (dart:ui/hooks.dart:174:5)
It occurs when the data fetching from firestore is cancelled. Then bottom navigation bar not work until restart app.
Error code
E/flutter (25456): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)]
Unhandled Exception: NoSuchMethodError: The method '[]' was called on
null. E/flutter (25456): Receiver: null E/flutter (25456): Tried
calling: E/flutter (25456): #0 Object.noSuchMethod
(dart:core-patch/object_patch.dart:53:5) E/flutter (25456): #1
_WeatherState.fetchLocationUpDate. (package:tast_project/screenes/screenweather.dart:31:27) E/flutter
(25456): #2 State.setState
(package:flutter/src/widgets/framework.dart:1148:30) E/flutter
(25456): #3 _WeatherState.fetchLocationUpDate
(package:tast_project/screenes/screenweather.dart:30:5) E/flutter
(25456): E/flutter (25456): #4
_WeatherState.initState (package:tast_project/screenes/screenweather.dart:42:5) E/flutter
(25456): #5 StatefulElement._firstBuild
(package:flutter/src/widgets/framework.dart:4355:58) E/flutter
(25456): #6 ComponentElement.mount
(package:flutter/src/widgets/framework.dart:4201:5) E/flutter (25456):
#7 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3194:14) E/flutter
(25456): #8 Element.updateChild
(package:flutter/src/widgets/framework.dart:2988:12) E/flutter
(25456): #9 SingleChildRenderObjectElement.mount
(package:flutter/src/widgets/framework.dart:5445:14) E/flutter
(25456): #10 Element.inflateWidget
(package:flutter/src/widgets/framework.dart:3194:14) E/flutter
(25456): #11 Element.updateChild
(package:flutter/src/widgets/framework.dart:2988:12) E/flutter
(25456): #12 ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:4243:16) E/flutter
(25456): #13 Element.rebuild
(package:flutter/src/widgets/framework.dart:3947:5) E/flutter (25456):
#14 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4206:5) E/flutter (25456):
#15 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4201:5) E/flutter (25456):
#16 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3194:14) E/flutter
(25456): #17 Element.updateChild
(package:flutter/src/widgets/framework.dart:2988:12) E/flutter
(25456): #18 SingleChildRenderObjectElement.mount
(package:flutter/src/widgets/framework.dart:5445:14) E/flutter
(25456): #19 Element.inflateWidget
(package:flutter/src/widgets/framework.dart:3194:14) E/flutter
(25456): #20 Element.updateChild
(package:flutter/src/widgets/framework.dart:2988:12) E/flutter
(25456): #21 SingleChildRenderObjectElement.mount
(package:flutter/src/widgets/framework.dart:5445:14) E/flutter
(25456): #22 Element.inflateWidget
(package:flutter/src/widgets/framework.dart:3194:14) E/flutter
(25456): #23 Element.updateChild
(package:flutter/src/widgets/framework.dart:2988:12) E/flutter
(25456): #24 ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:4243:16) E/flutter
(25456): #25 Element.rebuild
(package:flutter/src/widgets/framework.dart:3947:5) E/flutter (25456):
#26 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4206:5) E/flutter (25456):
#27 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4381:11) E/flutter
(25456): #28 ComponentElement.mount
(package:flutter/src/widgets/framework.dart:4201:5) E/flutter (25456):
#29 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3194:14) E/flutter
(25456): #30 Element.updateChild
(package:flutter/src/widgets/framework.dart:2988:12) E/flutter
(25456): #31 SingleChildRenderObjectElement.mount
(package:flutter/src/widgets/framework.dart:5445:14) E/flutter
(25456): #32 Element.inflateWidget
(package:flutter/src/widgets/framework.dart:3194:14) E/flutter
(25456): #33 Element.updateChild
(package:flutter/src/widgets/framework.dart:2988:12) E/flutter
(25456): #34 SingleChildRenderObjectElement.mount
(package:flutter/src/widgets/framework.dart:5445:14) E/flutter
(25456): #35 Element.inflateWidget
(package:flutter/src/widgets/framework.dart:3194:14) E/flutter
(25456): #36 Element.updateChild
(package:flutter/src/widgets/framework.dart:2988:12) E/flutter
(25456): #37 ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:4243:16) E/flutter
(25456): #38 Element.rebuild
(package:flutter/src/widgets/framework.dart:3947:5) E/flutter (25456):
#39 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4206:5) E/flutter (25456):
#40 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4381:11) E/flutter
(25456): #41 ComponentElement.mount
(package:flutter/src/widgets/framework.dart:4201:5) E/flutter (25456):
#42 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3194:14) E/flutter
(25456): #43 Element.updateChild
(package:flutter/src/widgets/framework.dart:2988:12) E/flutter
(25456): #44 ComponentElement.performRebuild
(package:flutter/src/widgets/framework.da
Flutter code weather
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
class Weather extends StatefulWidget {
#override
_WeatherState createState() => _WeatherState();
}
const ipkay = '14f4090b86e2548527113ccac56a5ae4';
class _WeatherState extends State<Weather> {
var temp = 0;
String city='';
//var id = 4099194;
String location ;
var textEditingController = TextEditingController();
fetchSearch(String input) async {
http.Response response = await http.get(
"http://api.openweathermap.org/data/2.5/weather?units=metric&appid=14f4090b86e2548527113ccac56a5ae4&q=" + input);
var result = json.decode(response.body);
setState(() {
location =result['name'];
});}
fetchLocationUpDate()async{
http.Response response = await http.get(
'http://api.openweathermap.org/data/2.5/weather?units=metric&appid=14f4090b86e2548527113ccac56a5ae4&q=$location');
var result = json.decode(response.body);
setState(() {
temp =result['main']['temp'];
city =result['name'];
});}
glo(String city){
fetchSearch(city);
fetchLocationUpDate();}
#override
void initState() {
super.initState();
fetchLocationUpDate();}
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea(
child: Container(
width: size.width,
height: size.height,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assetes/img/night.jpg',
),
fit: BoxFit.fill)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'${temp.toString()} C°',
style: TextStyle(color: Colors.white, fontSize: 30),
),
Text(
'$city',
style: TextStyle(color: Colors.white, fontSize: 30),
),
Card(
child: TextField(
onSubmitted: (String city) {
glo(city);
},
controller: textEditingController,
decoration: InputDecoration(
hintText: 'please entre city',
prefixIcon: Icon(Icons.search),
),
),
),
)
],
),
),
),
);
}
You can copy paste run full code below
Step 1: double temp = 0;
Step 2: glo need async and await
glo(String city) async {
await fetchSearch(city);
await fetchLocationUpDate();
}
Step 3: Check city exist or not
if (result["cod"] == 200) {
setState(() {
location = result['name'];
print("locaton $location");
});
}
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
class Weather extends StatefulWidget {
#override
_WeatherState createState() => _WeatherState();
}
const ipkay = '14f4090b86e2548527113ccac56a5ae4';
class _WeatherState extends State<Weather> {
double temp = 0;
//var id = 4099194;
String location;
var textEditingController = TextEditingController();
fetchSearch(String input) async {
http.Response response = await http.get(
"http://api.openweathermap.org/data/2.5/weather?units=metric&appid=14f4090b86e2548527113ccac56a5ae4&q=" +
input);
var result = json.decode(response.body);
print("fetchSearch ${response.body}");
if (result["cod"] == 200) {
setState(() {
location = result['name'];
print("locaton $location");
});
}
}
fetchLocationUpDate() async {
print("location to string ${location.toString()}");
http.Response response = await http.get(
'http://api.openweathermap.org/data/2.5/weather?units=metric&appid=14f4090b86e2548527113ccac56a5ae4&q=' +
location.toString());
print("LocationUpdate ${response.body}");
var result = json.decode(response.body);
if (result["cod"] == 200) {
setState(() {
temp = result['main']['temp'];
});
}
}
glo(String city) async {
await fetchSearch(city);
await fetchLocationUpDate();
}
#override
void initState() {
super.initState();
//fetchLocationUpDate();
}
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea(
child: Container(
width: size.width,
height: size.height,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
'https://picsum.photos/250?image=9',
),
fit: BoxFit.fill)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'${temp.toDouble()} C°',
style: TextStyle(color: Colors.white, fontSize: 30),
),
Card(
child: TextField(
onSubmitted: (String city) {
glo(city);
},
controller: textEditingController,
decoration: InputDecoration(
hintText: 'please entre city',
prefixIcon: Icon(Icons.search),
),
),
),
// RaisedButton(
// onPressed: () {
// glo();
// },
// )
],
),
),
),
);
}
}
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: Weather(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Every time I log in I get the below error.
I see there is some issue with my Navigator.pushReplacement, which gives error in the console but still allows me to Navigate.
Not sure how to fix this error.
The following code is what I am using. Please let me know if there is any I can get this error fixed.
class WelcomeScreen extends StatefulWidget {
#override
_WelcomeScreenState createState() => _WelcomeScreenState();
}
class _WelcomeScreenState extends State<WelcomeScreen>
with SingleTickerProviderStateMixin {
startTime() async {
var _duration = Duration(seconds: 5);
return Timer(_duration, navigationPage);
}
void navigationPage() {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => FirstTimeUserOnly(),
),
);
}
#override
void initState() {
super.initState();
startTime();
}
final int delayedAmount = 100;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Welcome'),
Logo(),
],
),
),
);
}
}
Here is the error I get
E/flutter (16323): Tried calling: findAncestorStateOfType<NavigatorState>()
E/flutter (16323): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
E/flutter (16323): #1 Navigator.of (package:flutter/src/widgets/navigator.dart:2115:19)
E/flutter (16323): #2 Navigator.pushReplacement (package:flutter/src/widgets/navigator.dart:1781:22)
E/flutter (16323): #3 _WelcomeScreenState.navigationPage (package:/welcome_screen.dart:23:15)
E/flutter (16323): #4 _rootRun (dart:async/zone.dart:1180:38)
E/flutter (16323): #5 _CustomZone.run (dart:async/zone.dart:1077:19)
E/flutter (16323): #6 _CustomZone.runGuarded (dart:async/zone.dart:979:7)
E/flutter (16323): #7 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1019:23)
E/flutter (16323): #8 _rootRun (dart:async/zone.dart:1184:13)
E/flutter (16323): #9 _CustomZone.run (dart:async/zone.dart:1077:19)
E/flutter (16323): #10 _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1003:23)
E/flutter (16323): #11 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:23:15)
E/flutter (16323): #12 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
E/flutter (16323): #13 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
E/flutter (16323): #14 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
E/flutter (16323):
try this, the timer is giving you the error
class WelcomeScreen extends StatefulWidget {
#override
_WelcomeScreenState createState() => _WelcomeScreenState();
}
class _WelcomeScreenState extends State<WelcomeScreen>
with SingleTickerProviderStateMixin {
Timer _timer;
void startTime() async{
_timer = Timer(new Duration(seconds: 5), navigationPage);
}
void navigationPage() {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => FirstTimeUserOnly(),
),
);
}
#override
void initState() {
super.initState();
startTime();
}
#override
void dispose() {
super.dispose();
_timer.cancel();
}
final int delayedAmount = 100;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Welcome'),
Logo(),
],
),
),
);
}
}
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);
}
},
),
];
}
}