How can I make a card clickable and navigate to another page inside TabBarView? - flutter

I'm trying to make a card clickable and navigate to another page 'forecastWeather.dart'. But I can't seem to figure out how I can fix the error I'm getting. The error message says
Another exception was thrown: Navigator operation requested with a context that does not include a Navigator.
I'm using a TabBarView with two tabs and one contains a card which should be clickable and navigate to another page 'forecastWeather.dart'. Please help!

In order to get use navigator.push, you must pass the context of your widget and have a MaterialApp somewhere in your tree, you do both, so the code should work, but it doesn't.
The reason is simple, the context you are passing is outdated, you are first creating the context when the build method begins, at that point, there is no material app, then you add a material app, but the context already exists, so the context you are passing when calling Navigator.push(context ... has no MaterialApp.
A possible fix is to use the Builder widget to make a new context after you create the MaterialApp widget:
#override
Widget build(BuildContext context) {
// context has no material app.
return MaterialApp(
home: Builder(
builder: (context) {
// this context does have a material app and is safe to use.
return DefaultTabController( ... );
}
),
);
}
Another fix is to move the code into a new widget with it's own context:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MainPage(),
);
}
}
class MainPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
// this context was created after the material app.
return DefaultTabController(...);
}
}

i suggest you to use get: ^4.6.1 package.
with this package you just need to use this for any navigation:
Get.to(ForecastWeather());
this package have so other features read its document here
[1]: https://pub.dev/packages/get

Related

Couldn't find the correct provider above this widget

I have a problem using Flutter Provider...
After Onbording screens I click to Next Button and needs to show me Welcome Screen (where i choose to log in with phone number)
But after clicking to Next Button i get this error - Could not find the correct Provider above this WelcomeScreen Widget
class _WelcomeScreenState extends State<WelcomeScreen> {
#override
Widget build(BuildContext context) {
final ap = Provider.of<AuthProvider>(context, listen: true);
return Scaffold(
body: SafeArea(
child: Center(
Make sure your Provider<> widget is present and at the root(like parent of MaterialApp for instance) to make sure it is in widget tree across rebuilds.
As far as I can see your code, you're calling Provider watch in welcome screen which prolly doesn't have the Provider in its tree. Move the watch to OnboardingScreen.

what is buildcontext in flutter?

What is the purpose of it in flutter framework?. I want to know the flow of build context.
class MyAwesomeWidget extends StatelessWidget{
#override
Widget build(BuildContext context)
return Container(
child: Text("Hello"),
);
}
According to some research as it says: "BuildContext is a locator that is used to track each widget in a tree and locate them and their position in the tree. The BuildContext of each widget is passed to their build method. Remember that the build method returns the widget tree a widget renders. Each BuildContext is unique to a widget."
So your all application is basically consist of tree structure and following it from the root of your app.

how do you share data between viewmodels in Flutter Provider state management?

I am new to flutter Provider state management. If each view has its own viewmodel, how do you share data between viewmodels?
Lets say you have a viewmodel with a list in it, in one screen you want to show the list, and in another screen you want to show the list count?
You can place ViewModels on the top of widget tree, before MaterialApp
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: <SingleChildWidget>[
ChangeNotifierProvider<ViewModel1>(create: (_) => ViewModel1()),
ChangeNotifierProvider<ViewModel2>(create: (_) => ViewModel2()),
],
child: MaterialApp( ... );
);
}
}
so you can access both viewmodels everywhere

Get the Global Context in Flutter

Is there any way to get the global context of Material App in Flutter. Not the context of particular screen.
I am trying to get the context but it gives me the context of particular screen but I wan the context of MaterialApp.
If above solution does not works please try this solution.
Create the class. Here it named as NavigationService
import 'package:flutter/material.dart';
class NavigationService {
static GlobalKey<NavigatorState> navigatorKey =
GlobalKey<NavigatorState>();
}
Set the navigatorKey property of MaterialApp in the main.dart
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: NavigationService.navigatorKey, // set property
)
}
Great! Now you can use anywhere you want e.g.
print("---print context:
${NavigationService.navigatorKey.currentContext}");
Assign a GlobalKey() to the MaterialApp which you can put in a separate class, let's call it App :
#override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: App.materialKey, // GlobalKey()
)
}
Now wherever you want to get the context of the MaterialApp, you just have to call :
App.materialKey.currentContext
Here I'm printing MaterialApp context :
print('Material App Context : ${App.materialKey.currentContext}');
OUTPUT :
flutter: Material App Context : MaterialApp-[GlobalKey#4fab4](state: _MaterialAppState#4bb44)
If you use Getx State Management you can use;
GetMaterialApp(
navigatorKey: Get.key,
);
Reach out with;
BuildContext? context = Get.key.currentContext;

how to pass data to another screen using bloc in flutter

hello I am new in flutter and bloc, I imagine that I have 2 screens (login and home screen). In login screen I am using bloc that post data and I want to call that data in my home screen. Can someone give me example to do that?
There are many ways to do that, I can name a few.
You navigate to the new Widget (the screen) and pass to that Widget constructor the data you want it to have.
You can use Provider to provide that data and wrap the new screen on it, then navigate to the new screen.
If this is some data that should be accessed across the app, you could provide the entire BLoC to the entire App and get the BLoC's reference on this new screen and then get the data directly from the BLoC.
If you just want to pass a value to home page from login page, you can do like this:
class Home extends StatelessWidget {
final String username;
Home(this.username);
#override
Widget build(BuildContext context) {
return Container();
}
}
class Login extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
return Home('flutter');
}));
}),
);
}
}