I want to have some navigation inside of my dialog. In the past I just used a Navigator widget for that:
#override
Widget build(BuildContext context) {
return Navigator(
key: _navigatorKey,
initialRoute: routeHome,
onGenerateRoute: _onGenerateRoute,
);
}
But now I switched to go_router. Is there any way I can accomplish the same with go_router? To have a separate Navigation inside of my dialog?
Related
I used to had two widgets where the first displays a list and the second is the detail page of a specific item in the list.
class WidgetA extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildAppBar(context),
body ListView.builder(...)
}
}
class WidgetB extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildAppBar(context),
body ....
}
}
such that WidgetA navigates to WidgetB.
Navigator.push(context,MaterialPageRoute(builder: (context) => WidgetB()));
But since I want a nice animation for the transition, I now use a Hero widget in both Widgets.
// Widget B
#override
Widget build(BuildContext context) {
return Hero(
tag: someObject,
);
}
But now the problem is that whenever WidgetB wants to display a snackbar, it is not visible there. If you would however navigate back to WidgetA before the snackbar would have disappeard, you can see it there.
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
duration: const Duration(seconds: 3), content: Text('some text'),
));
I looked at the Scaffold documentation which states
It is typically not necessary to nest Scaffolds. For example, in a tabbed UI, where the bottomNavigationBar is a TabBar and the body is a TabBarView, you might be tempted to make each tab bar view a scaffold with a differently titled AppBar. Rather, it would be better to add a listener to the TabController that updates the AppBar
So I also tried returning a Simple Column in WidgetB which is wrapped inside a ScaffoldMessenger but none of these solutions works... I did some lookup online and people talk about it that this is intended behaviour. But no official sources say so. How could I nonetheless display a snackbar in the detail page while still using nice Hero transitions?
I have created a widget with a scaffold and called a widget in it as
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text("Everything Store"),
),
body: Register(),
);
}
}
the Register component doesn't have a scaffold in it, but when I try to navigate from the Register widget to another one that also doesn't have a scaffold too, so I used
onPressed: () => {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => login_page()))
},
I got an error as " No Material widget found. "
So is there a way to have one scaffold or should I make a scaffold for each widget?
The scaffold is one of the main widgets that helps you build up the UI screen on a device but a screen doesn't necessarily need it. The error that you are getting it might be because you are not passing the Widget class correctly.
Try to replace login_page() with the class name like so Register().
I have declared MultipleProviders in my widget and i want to use it to change the color of the App by assaining the variable to the ThemeData Primary swatch but it's giving me this error related to provider . and i have use in other widgets and it's working .i think i am getting this error bacause i am using it in the same widget how i can solve it ?
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
var u = Provider.of<prov>(context);
return MultiProvider(
providers: [ChangeNotifierProvider(create: (_)=>prov())],
child: GetMaterialApp(
theme: ThemeData(primarySwatch: u.col),
title: 'Material App',
home: f(),
),
);
}
}
this is the error
Error: Could not find the correct Provider above this MyApp Widget
This happens because you used a BuildContext that does not include the provider
of your choice. There are a few common scenarios:
You added a new provider in your main.dart and performed a hot-reload.
To fix, perform a hot-restart.
The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
You used a BuildContext that is an ancestor of the provider you are trying to read.
Make sure that MyApp is under your MultiProvider/Provider.
This usually happens when you are creating a provider and trying to read it immediately.
For example, instead of:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// Will throw a ProviderNotFoundError, because `context` is associated
// to the widget that is the parent of `Provider<Example>`
child: Text(context.watch<Example>()),
),
}
consider using builder like so:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// we use `builder` to obtain a new `BuildContext` that has access to the provider
builder: (context) {
// No longer throws
return Text(context.watch<Example>()),
}
),
}
You're getting the error because the context you're using does not have access to the provider.
The solution is like it says in the error message: you can use a builder instead of a child property for your provider. That creates a new context that reads the provider created.
You should change your build method to this.
Widget build(BuildContext context) {
return MultiProvider(
providers: [ChangeNotifierProvider(create: (_)=>prove())],
//From here is where you make the change
builder: (context, child) {
var u = Provider.of<prov>(context);
return GetMaterialApp(
theme: ThemeData(primarySwatch: u.col),
title: 'Material App',
home: f(),
),
);
}
As the title says, I have a String parameter and when I load the Home Stateful Widget I would like to open this bottom sheet if the parameter is not null.
As I understood I can't call showModalBottomSheet() in the build function of the Home widget because it can't start building the bottom sheet while building the Home Widget, so, is there a way to call this immediately after the Home Widget is built?
One of the solutions might be using addPostFrameCallback function of the SchedulerBinding instance. This way you could call showModalBottomSheet after the Home widget is built.
import 'package:flutter/scheduler.dart';
...
#override
Widget build(BuildContext context) {
SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
//Your builder code
},
);
});
//Return widgets tree for Home
}
Here's one way:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
child: Text('heyooo'),
);
}
);
});
return Scaffold(
appBar: AppBar(),
body: Container(),
);
}
}
I've being studying Flutter for about 4 days, it's becoming tedius, now I want put something together. I want to show a different AppBar content at each screen. But it seems my Scaffold's AppBar is begin ignored.
Here's my code:
class Login extends StatelessWidget{
Widget build(BuildContext context){
return Scaffold(appBar: AppBar(title:Text( 'Identification') ), body: Stack( children: [RaisedButton( child: Text("logar"), onPressed: () => {
Navigator.pushNamed(context, '/other-screen')
})]));
}
}
The app bar above it seems invisible, doesn't show
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'title placedholder',
initialRoute: '/',
routes: {
'/' : (BuildContext context) => Login(),
'/other-screen' : (BuildContext context) => Scaffold(body: Row(children: <Widget>[],))
},
I have copied your code into DartPad and the first AppBar seems to be Ok.
The problem is with your second page.
Every time you create a new Scaffold, you need to add an AppBar to it.
Try running flutter clean and then running it again.
I find this fixes most issues when the code is correct but the application doesn't reflect the intended behaviour.