No Overlay widget found despite Scaffold and MaterialApp - flutter

I'm using Riverpod as global state manager on my application; in this case, I'm using it to handle the application's launch: if there is a profile persited on device, it will go directly to one screen based on the user's role, if there is no such profile, it will send us to the login screen.
Given a persisted user I am getting the next bug:
======== Exception caught by widgets library =======================================================
The following assertion was thrown building Tooltip("Open navigation menu", dirty, state: _TooltipState#4e2ac(ticker inactive)):
No Overlay widget found.
Tooltip widgets require an Overlay widget ancestor for correct operation.
The most common way to add an Overlay to an application is to include a MaterialApp or Navigator widget in the runApp() call.
The specific widget that failed to find an overlay was: Tooltip
"Open navigation menu"
The relevant error-causing widget was:
AppBar file:///home/luisalaguna/Projects/thesis_cancer/lib/core/presentation/widgets/header.dart:17:12
When the exception was thrown, this was the stack:
#0 Overlay.of.<anonymous closure> (package:flutter/src/widgets/overlay.dart:306:9)
#1 Overlay.of (package:flutter/src/widgets/overlay.dart:309:6)
#2 _TooltipState.build (package:flutter/src/material/tooltip.dart:457:20)
#3 StatefulElement.build (package:flutter/src/widgets/framework.dart:4612:27)
#4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4495:15)
Header is an AppBar widget; this bug would not be strange if all the widget wouldn't be wrapped by an Scaffold and a MaterialApp widgets:
The code on main file is this:
class CancerApp extends HookWidget {
#override
Widget build(BuildContext context) {
final _appRouter = AppRouter();
final bool darkTheme = useProvider(darkThemeProvider);
final launcherState = useProvider(launcherProvider);
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
return MaterialApp.router(
title: 'Thesis Cancer',
theme: darkTheme ? ThemeData.dark() : ThemeData.light(),
routerDelegate: _appRouter.delegate(),
routeInformationParser: _appRouter.defaultRouteParser(),
// home: SplashScreen()
builder: (context, router) => launcherState.when(
loading: () => SplashScreen(),
needsProfile: () => LoginPage(),
profileLoaded: () => MainScreen()),
);
}
}
About the launcher notifier, you can see it here.
After rafactoring this workflow I am getting this bug, i didn't get it when the profileLoaded state was returning the user(I was getting another issue).
What can be the problem?

Add applyElevationOverlayColor: true, on your Theme

Related

flutter/dart: Looking up a deactivated widget's ancestor is unsafe

I have used persistent_bottom_nav_bar 5.0.2 package and from the first tab page which is homepage I navigate to further some pages and than finally I use the following navigator to come back to this page on same tab
Navigator.of(context).pushAndRemoveUntil(
CupertinoPageRoute(
builder: (BuildContext context) {
return HomePage();
},
),
(_) => false,
);
I Navigate successfully but when I click on this tab it throw this exception
════════ Exception caught by gesture ═══════════════════════════════════════════
The following assertion was thrown while handling a gesture:
Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
I even don't know the reason as well as solution so any help will be appreciated.
You are removing all the screens below HomePage from the stack.
pushAndRemoveUntil as name suggests pushes a new Screen in stack and removes all the other screens from stack as a result theirs no screen available to pop except the current HomePage.
Instead use only
if (mounted) {
Navigator.of(context).push(
CupertinoPageRoute(
builder: (BuildContext context) {
return HomePage();
},
),
(_) => false,
);
}

Flutter Duplicate global key when navigating to original route working with Persistence navigation

I am an Android developer, new to flutter. I wanted persistence bottom nav in my app. So I implemented it. But I didn't need the bar in Videoplayer.
"homepage>> episodepage >> videoplayer."
So I implemented the following solution.
Navigator.of(context, rootNavigator: true)
.push(MaterialPageRoute(builder: (context) => PlayerPage(widget.list[index])));
which worked perfectly, But another problem was raised, back pressed closed the app. I didn't find the solution to go back to episodesPage() . but I manage to make it work with a small trick.
So, I created a variable in class C
static Widget? MainPage;
Then on my Main inside Myapp() I assign the variable
class MyApp extends StatelessWidget {
MyApp({Key? key}) : super(key: key);
Widget MainPage = MyHomePage(title: 'Flutter Demo Home Page');
#override
Widget build(BuildContext context) {
C.MainPage= MainPage; // here
return MaterialApp(
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.light,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MainPage,
); }}
And then on VideoPlayer() inside WillPopScope. I was able to navigate back to my previous Episode() page.
Widget? child = C.MainPage;
if (child != null) {
Navigator.of(context, rootNavigator: true)
.pushReplacement(MaterialPageRoute(builder: (context) => child));
}
It is working perfectly. But when I check logs an error was showing. How should I remove the error? or what's the better solution.
The following assertion was thrown while finalizing the widget tree:
Duplicate GlobalKey detected in widget tree.
The following GlobalKey was specified multiple times in the widget tree. This will lead to parts of the widget tree being truncated unexpectedly, because the second time a key is seen, the previous instance is moved to the new location. The key was:
- [LabeledGlobalKey<NavigatorState>#a352a]
This was determined by noticing that after the widget with the above global key was moved out of its previous parent, that previous parent never updated during this frame, meaning that it either did not update at all or updated before the widget was moved, in either case implying that it still thinks that it should have a child with that global key.
The specific parent that did not update after having one or more children forcibly removed due to GlobalKey reparenting is:
- NavigatorTab(state: _NavigatorTab#34e63)
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 BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2991:15)
#1 BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:3016:8)
#2 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:893:19)
#3 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370:5)
#4 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15)
#5 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083:9)
#6 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:997:5)
#10 _invoke (dart:ui/hooks.dart:151:10)
#11 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
#12 _drawFrame (dart:ui/hooks.dart:115:31)

Flutter Navigation 2.0 + Bloc

I am currently trying to learn Navigation 2.0 in conjunction with BLoC.
I've followed the raywenderlich's guide [1] successfully (it's a bit outdated) and i tried to move forward managing the state with BLoC (this guide uses Provider) and when i did it successfully, i tried to take a step further and i tried to follow JalalOkbi's guide [2] because of a more advanced abstraction level provided. The third link [3] is the github repo with the full (now failing) project.
But after 5 days of trying i stumbled in several errors and i can't figure this out: i am currently facing this error:
I/flutter (10212): looking for /
I/flutter (10212): found Splash("null", null, null)
I/flutter (10212): looking for /
I/flutter (10212): found Splash("null", null, null)
════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building Builder:
The settings getter of a page-based Route must return a Page object. Please set the settings to the Page in the Page.createRoute method.
'package:flutter/src/widgets/navigator.dart':
package:flutter/…/widgets/navigator.dart:1
Failed assertion: line 3361 pos 9: 'entry.route.settings == page'
════════ Exception caught by widgets library ═══════════════════════════════════
A GlobalKey was used multiple times inside one widget's child list.
The relevant error-causing widget was
MaterialApp
lib\main.dart:40
════════════════════════════════════════════════════════════════════════════════
[1] https://www.raywenderlich.com/19457817-flutter-navigator-2-0-and-deep-links
[2] https://medium.com/#JalalOkbi/flutter-navigator-2-0-with-bloc-the-ultimate-guide-6672b115adf
[3] https://github.com/msimoncini90/flutter_navigation_2.0
If your page object is defined like
class SplashPage extends Page {
#override
Route createRoute(BuildContext context) {
return MaterialPageRoute(
builder: (BuildContext context) => const SplashScreen(),
);
}
}
The issue is that there is a missing setting in the page definition, which is what the error is showing. The correct code looks like
class SplashPage extends Page {
#override
Route createRoute(BuildContext context) {
return MaterialPageRoute(
settings: this,
builder: (BuildContext context) => const SplashScreen(),
);
}
}
Notice that the settings: this parameter, which solves what the error is describing.

When I make Widget build in flutter, can I make it without Scaffold?

I'm trying to make an app with just a webview with flutter.
1). When I make Widget build, can I make it without Scaffold like the code below?
2). I want to reduce even one frame.
If I build without scaffold will it help reduce frames?
And 3). I'm only making webviews, can I remove SafeArea as well?
return Container(
child: SafeArea(
child: WebView(
..
),
)
);
}
To answer your question shortly:
The Scaffold or a Material widget is required if your widget is a Widget (such as TextField) that required a Material parent widget. No if your widget is not.
If you omit the Material parent widget, an error will happens (See the end of the post for more info).
In this case, since your widget is a WebView (which I assume is from this package webview_flutter), you don't need a Scaffold.
You can simply use it like this:
import 'dart:io';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewExample extends StatefulWidget {
#override
WebViewExampleState createState() => WebViewExampleState();
}
class WebViewExampleState extends State<WebViewExample> {
#override
Widget build(BuildContext context) {
return WebView(
initialUrl: 'https://flutter.dev',
);
}
}
P/s: The error when you omit a Material parent will be like:
I/flutter ( 5187): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 5187): The following assertion was thrown building InputDecorator(decoration: InputDecoration(hintText:
I/flutter ( 5187): "Type something"); baseStyle: null; isFocused: false; isEmpty: true; dirty):
I/flutter ( 5187): No Material widget found.
I/flutter ( 5187): InputDecorator widgets require a Material widget ancestor.
I/flutter ( 5187): In material design, most widgets are conceptually "printed" on a sheet of material. In Flutter's
I/flutter ( 5187): material library, that material is represented by the Material widget. It is the Material widget
I/flutter ( 5187): that renders ink splashes, for instance. Because of this, many material library widgets require that
I/flutter ( 5187): there be a Material widget in the tree above them.
I/flutter ( 5187): To introduce a Material widget, you can either directly include one, or use a widget that contains
I/flutter ( 5187): Material itself, such as a Card, Dialog, Drawer, or Scaffold.

Is it normal that when I run my flutter code the first time it is rederized 2 times? (I only use one class )

I am new to flutter. Something worries me, I don't know if it is normal. I know the code will render if the widget is of type StateFulWidget. But in this case, I have a stateLessWidget and for some reason it renders 2 times. is this normal?
this is my code:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
print("main");
return MaterialApp(title: 'Provider Example', initialRoute: '/', routes: {
'/': (context) => Page2(),
});
}
}
class Page2 extends StatelessWidget {
Page2() {
print("page2");
}
#override
Widget build(BuildContext context) {
return Container();
}
}
this is the output:
Restarted application in 832ms.
I/flutter ( 4439): main
I/flutter ( 4439): page2 --> next two lines are the same, the widget is render again
I/flutter ( 4439): main
I/flutter ( 4439): page2
Flutter build method is what creates and return your rendered widget on the screen, so the build must be called everytime something change in the UI, and it need to rebuild. According to the Documentation
The build method will be called after:
After calling initState.
After calling didUpdateWidget.
After receiving a call to setState.
After a dependency of this State object changes (e.g., an InheritedWidget referenced by the previous build changes).
After calling deactivate and then reinserting the State object into the tree at another location.
So even if you have a Stateless Widget, flutter can and will rebuild multiple times, this why you should avoid putting logic handlers inside your Widgets, specially the build, let this method as simple as possible with only what it actually needs to build the widget.
Also, during animations, transitions... Your widget will be rebuild a lot of times in order to perfom the animation. If you want to avoid unnecessary builds there's some ways you can do it, by making using of the const widgets, if you that a certain Widget won't change during runtime like a Text('Hi') this kind of Widget just need to be build once, so you can use a const keyword to it.