Trigger a function in TabBar based on a Floating button from parents - flutter

I am using flutter for my app.
I have a TabBarView that I would loop as shown as below.
TabBarView(
controller: controller,
children: visibleTab
.map((e) =>
TabDataWidget(
data: e,
)
).toList(),
);
Each Tab would be populated by the TabDataWidget (as shown above).
I have a Floating button, that I wanted to trigger a function inside the TabDataWidget when the user click at the Floating button.
If the user scroll to Tab Index 1, when the user clicks at the Floating button, I wanted to call a function inside TabDataWidget to process data inside Tab Index 1. Similarly, if the user scrolls to Tab Index 2, when the user clicks at the Floating button, I wanted to call a function inside TabDataWidet.
How can I achieve this in Flutter?

It seems like you need a state management solution as you want to access your data/methods from several widgets. Having a widget calling another widget's function to change state is not recommended as it can get messy and difficult to manage your state. Instead you should lift your state up in the hierarchy and use this state across the widgets you want. Flutter Docs have a great article that explains how you can approach state management. Different solutions exist but you might have a look at the provider package. Also there is a useful talk by the Flutter team explaining common anti patterns and how provider can help to overcome these.

Related

How to determine if a Widget is Stateful or Stateless in Flutter?

I understand the basics here. If my data is going to change it should be stateful so I can update it otherwise stateless.
My question is more oriented in a bottomnavigation scenario. So, I have 3 tabs in my bottomnavigator (Profile, Home, Settings). The entry point is Home which is a stateful Widget.
The other two Widgets I want to basically populate the information in them with the api data.
The Problem
If I am in the Home screen and I click in the Profile icon in the bottomnavigator it does not load the information from the api. Even if it does, If I click in the Home screen and click again in the Profile screen to go back, the information does not refresh.
Solution
So what would be the way to handle this? I expect that if I click in each of the bottomnavigation items the information is refreshed with the api data. Is this because the Widgets are Stateful or Stateless or I am missing something else?
By default, the pages in Bottom Navigation bar refreshes/rebuild when they are are tapped on.
Make sure a few things in your app-
You are not using a "indexed stack" or any similar widget for these pages. These widgets preserves the state of your page
The navigation is taking place on its own. You have not defined any Navigator.Push etc for tap's in navigation bar.
You should call the API inside the initState method of that particular page. Like if you need profile details, call the api for profile information inside the initState method of Profile Tab and not the "Scaffold" page which has the navigation bar.

Preserving the State of a Drawer in Flutter

I have a stateful Scaffold widget, where the body contains a list of entities with various properties (e.g. shoes or cars) and Drawer widget, which is empty at first, except for two buttons at the bottom ("Cancel" and "Filter") and a FAB. The user can add various filters with the FAB (e.g. the user can add a shoesize-filter, or a color-filter).
The problem I have is the following: Let's say the user selects various filters and works with them (i.e. ticks checkboxes, enters a shoesize, changes sliders, etc.). When the user is ready to apply the filters, he can click the "Filter" button, which closes the Drawer (onTap -> callback -> Navigator.of(context).pop()). But when the user wants to go back, reopen the Drawer, and adjust one of the filters, it obviously doesn't work, since the widget is being rebuilt from scratch.
Currently, the way the filtering works is, once the "Filter" Button is pressed, all the various values from the added filters are collected into an object FilterPackage, which is then passed via callback to the Scaffold widget, which then applies the values from the FilterPackage to the list of entities.
One solution I came up with, would be feeding this FilterPackage object to the Drawer widget in its constructor, which would provide all the information necessary to rebuild the widget just how it has to be.
Is that a reasonable solution? I have already made some research, but struggled finding a solution on what would clearly be the best and recommended way to preserve the drawer's state. Using PageStorage / PageStorageBucket seems overly complicated for this case. Or am I wrong?
Thanks in advance for any guidance.

When to use new Screens in Flutter instead of TabBarView

I am fairly new to Flutter and I try to understand when and why it would be necessary to navigate to a new screen. Most apps keep the same AppBar, Drawer & BottomNavigationBar (if any) through all the different "screens". Wouldn't it be easier to just have one single TabBarView, or only replace the Scaffold's body ?
I have a hard time to really understand the concept of why there needs to be a new Scaffold when routing. I couldn't find anything helpful in the official Flutter doc, even the Cookbook show you a Navigation example with 2 completely new screens just to show a different Text widget inside the Scaffold's body.
Also, what about the efficiency of always rebuilding the whole Scaffold ?
When you route to new page, the previous page stored in history of navigator, so you can easily return to previos page just clicking Back button. In principle all depends on what you need. You may use new page with its own Scaffold as well as one page with single Scaffold and different body widgets. For last case you need to controll Back button manually so this way is enough expensive in development.

How to show Snackbar without Context object in flutter?

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());

How to update StatefulWidget from other class?

First of all, I'm a real beginner with Flutter, so I have probably not even grasped the basic design patterns yet. My problem is probably simple for someone who understands flutter. Here goes:
I have a tabbed GUI in my app and a floating action button. Each tab has a list that I want to update using that action button (FAB). The easy way to do this seemed to have one action button for each tab, but I read that you should not do this in flutter. So I made the button "global" and call a method on the current tab when the button is pressed. The method then adds some data that should be shown in the list, but the problem is that the list of course isn't actually updated just because I add data. The setState() is never called inside that list widget.
All the exampels I've found are very simple with the FAB being inside the list having access to its setState() method. But in my case I'm outside the list. How do I solve this? Notifier? Stream? I'm lost...
I think the correct solution is to use a "Stack" and "Positioned" widged like:
- Stack
- Scaffold
- TabBar
- Positioned
- FloatingActionButton