I have a Tabbar with two tabs. The Tabbar has its own Appbar which is used by both tabs. How do I have the sort button run custom (set state) functions inside each tab's stateful widget? Alternatively, is it possible for each tab to have its own unique Appbar? I am not sure what best approach is here.
Example method inside one of the tabs:
class _TabAState extends State<TabA> {
void sort() {
setState(() {
myList.sort((a, b) => b.dueDate.compareTo(a.dueDate));
});
}
...
Sort button:
IconButton(
icon: Icon(Icons.sort),
onPressed: () => DefaultTabController.of(context).index == 0
? TabA.sort() // Does not work
: TabB.sort(), // Does not work
),
Regarding your concern if this approach is the best approach:
From the documentation
The Scaffold was designed to be the single top level container for a MaterialApp and it's typically not necessary to nest scaffolds.
Based from this statement, I suggest that it's probably not a good idea to nest multiple Scaffold inside another Scaffold. This is related to your concern, whether to have nested AppBar inside a Scaffold, given that you can only have one AppBar per Scaffold.
I personally do not recommend the calling static or non static method from other Flutter Widget classes (eg. widget that serves as a standalone screen for your app) for executing the business logic of your application. Perhaps, you can continue implementing the business logic of your application using widgets such as ScopedModel and architectural patterns such as BloC, Redux or Mobx.
Further reading:
https://api.flutter.dev/flutter/material/Scaffold-class.html
https://www.didierboelens.com/2019/04/bloc---scopedmodel---redux---comparison/
How to call method from another class in Flutter(Dart)?
Related
I am searching this topic and I must confess, I love the using function widgets for my applications. And in the my flutter experience, I never got any error or any unwanted result with this approach(I mean using function widgets).
But while my search, I couldn't totally understand the reason, why I must use the stateless widgets but not function widgets.
An example; I want to create a page, using scaffold, and appar.
My page must be statefull so I want to use
Scaffold scaffold({String pageTitle, Widget body, Widget floatingActionButton, Widget appBarLeading})=>Scaffold(
appBar: CustomAppBar(pageTitle: pageTitle, leading: appBarLeading),
body: body,
floatingActionButton: floatingActionButton,
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
backgroundColor: Colors.blueGrey[50],
);
this code and, my custom appbar coming from Stateless Widget.
So what happen if I use this structure for the beginning ?
İf I use the setstate, my appbar creating from to beginning or used from widget three ?
I can understand the reasons why must use stateless widget because it has final variables and this way, it is reused in the program behalf but What happen If I use stateless widgets in my function widgets ?
Please help me for understanding this topic.
Thank you very much.
So this is the case, I have two MaterialApps in a Stack widget, I made it like that so they have separate navigation routes. The problem is, I need to navigate to a page which is on MaterialApp 1 from MaterialApp2.
Even clearer example: Button is on MaterialApp 2, I need to press that button and page on MaterialApp 1 shows up. How do I do this? Whenever I use Navigator.of(context).push() on MaterialApp 2, it of course changes the page on that MaterialApp...
It's not necessary that a Navigator.push() called in a specific MaterialApp widget will be doing push operation on that app's stack. Which MaterialApp's stack to choose depend on the Buildcontext you pass in the push function.
You can do that by saving the BuildContext of both materialApps globally and using whichever you want in Navigator.push().
Wrap the children of both MaterialApps in Builder widget to extract the BuildContext of both. Say of app1 it's context1 and app2 it's context2.
Save both of them globally using static variables in a different class say "Data".
Now while calling Navigator.push() anywhere in your app, instead of simply putting that widget's context in the context parameter use the contexts of the materialApps you saved earliers.
Say you want to push a page on MaterialApp1's stack, do
Navigator.push(Data.context1,/*Rest of the builder function as it is*/);
Also instead of using two different MaterialApps just for getting two seperate navigators, you can try using the Navigator widget.
I am really confused about how Flutter manages multiple navigation stacks at once, and switches between them with the BottomNavigationBar. So far I have managed to swap the body of my root Scaffold with Widgets, and can also change state on the Scaffold to change the AppBar title and set the index of the BottomNavigationBarItem. I can also see how setting routes on the MaterialApp will allow me to push and pop other screens. The problem is that when you have a tab bar navigation pattern, you want to be able to manage separate stacks. If I am 3 levels deep into a section and switch tabs, I expect to be in the stack for that particular section, and be able to jump between them.
How is this managed with Flutter? Ideally, the app should have a Main App Scaffold to define the BottomNavigationBar, the Drawer, and the main logic for switching between the different root level screens. These Screens should then manage their own AppBar and related actions for that section.
I'd really like to understand this before I go any further with Flutter, because right now, the thought of having to manage everything with one Scaffold fills me with dread.
I'm guessing that when you use Navigator it uses the Context to keep the stacks within the context of the screen that initiated the push, but I still don't understand how it keeps the Scaffold separate.
Any insight greatly appreciated.
This wonderful article gives me the answer: https://medium.com/flutter/getting-to-the-bottom-of-navigation-in-flutter-b3e440b9386
You need to use an IndexedStack for your main section switcher, and then use a Widget that returns a Navigator for each of the main sections. This Navigator sets the routes for that section (if known), but could just be the root.
I don't know if there is already a navigation pattern, or naming convention used by the Flutter community for this, but I have used $(Section)Navigator. Here's an example of a StatelessWidget I created for my test:
class DashboardNavigator extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Navigator(
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute(
settings: settings,
builder: (BuildContext context) {
switch (settings.name) {
case '/':
return DashboardRoot();
case '/login':
return ScreenLogin(destination: allDestinations[0]);
default:
return DashboardRoot();
}
},
);
},
);
}
}
This was mainly taken from Hans Muller's article which has been a great help.
There are many times where we would have had separation of concerns when it comes to UI code and business logic. This is reflected in most of the state management solutions that we use in Flutter.
In many of the state management solutions where the business logic is outside the view file ( widget file) , there are cases where we want to show the snackbar based on the logic in flutter.
But to show a Snackbar we first need a context object. I have used a NavigatorState to navigate without context. But I don't know if there is a way to show SnackBar without context.
Can someone provide a solution for this ?
Also it would be very helpful if you could provide a Utility method that manages the state internally and whenever user wants to show snackbar would just call that utility method from his logical part of code.
You can specify scaffoldMessengerKey as a property of MaterialApp and then ScaffoldMessenger can be directly used without BuildContext.
I think you can do the same way as navigatorKey.
ref: https://api.flutter.dev/flutter/material/MaterialApp/scaffoldMessengerKey.html
Check this answer for more details on how to implement this into your application, with some code examples.
You definitelly can show a piece of information without a context, something similar to a snackbar, however, it is not a snackbar.
If you use the package Get, you can navigate without context, open dialogs, snackbars or bottomsheets from anywhere in your code. However, the snackbars in particular have some issues.
As it doesn't check for a Scaffold, the snackbar is shown directly in the bottom of your screen. This means that if you have a BottomNavigationBar, it will be covered or partially covered by it.
It also means that if you have a FloatingActionButton, it won't be responsive to the snackbar position, as opossed to the normal snackbar.
So to sum up, with Get, you can have snackbars without context but you will have to make some sacrifices in your UI.
Example
final bottomSnackBar = GetBar(
isDismissible: false,
showProgressIndicator: true,
message: 'Processing...',
);
bottomSnackBar.show();
somethingAsync().then((_) => bottomSnackBar.hide());
I am trying to build an app in Flutter in which I have multiple pages, each with their specific actions in the app bar. I would like to add a Drawer to the app which contains a list of page names that take them to the respective pages. I learnt that both AppBar and Drawer widgets have to be part of a Scaffold widget. Currently, all my pages are basically StatefulWidgets with the build method returning a complete Scaffold widget. If I want to include a Drawer, I think I will have to add the drawer object in each of my page. Is there a better way/pattern to do this?
Write the code for the drawer once and enclose it in a function. Then just call the function each time for that drawer.
eg)
drawer: myDrawer()
In one of my Apps, I have something similar. My Drawer is in the app class which is called in the main. This app class calls the home classes. My app class is also Stateful.
Each home class has his own Appbar and Search function.
The Drawer is called only in the app class.
Tell me if this explanation is okay for you or if you need a sample code.