I have two custom widgets:
An output field to display an amount of money
A digital keyboard with number keys to enter an amount
The layout image is here
When a user taps on a number key of the keyboard widget, I want this number to be added to the output field widget. It's just a one-time event for the keyboard and the parent widgets. The pressed number should be added only to the state of the output field's widget, not the parent's widget.
How do I do that properly?
I've implemented this making the output's widget State class public with a public method "onKeyPressed". Then, I use a GlobalKey to make a direct call to that public method when a number on the keyboard is pressed. But this solution seems awkward and going against the UI architecture.
Related
Flutter widget update pattern is a little bit confusing when coming from "old/classic" win32.
For instance :
I have a widget "button" => I click on it => I update a cell in a widget "datatable".
With classic API (VCL, Net Forms, ...) I get the address of button (by name, id, ...) and call directly
datatable_address.cell[x,y] = new_value;
I understand that I have to use setState() but do I need to create an "event" in Datatable (to run its setState()) and fire up this event from my button ?
(BloC seems pretty close to Qt signals)
The difference is composition vs aggregation. The widgets themselves are immutable so you can't change the value inside a widget.
What you can do is create a new object with latest values. Flutter framework will take care of the rest. For example,
when you do setState in parent widget of both button as well as datatable, you build method of said widget is called. Now, you will create a new datatable object with updated cell values. Internally, flutter will handle this.
You can only do setState in State class which is not immutable which is linked to Stateful widget which themselves are immutable.
This architecture comes with its own set of problems like if you need to update some UI based on some button press, you will have to have the logic inside the common widget of both the affected widget and button. That's where Stream/Bloc comes into picture.
I'm fairly new to Riverpod but it seems that using a ConsumerWidget as the body of a screen is a bad practice because the screen is rebuilt when not needed.
For example:
the main widget (the screen itself) is a ConsumerWidget
somewhere in the hierarchy I have a list of clickable buttons, for which I'm watching a ChangeNotifierProvider to update a selected index (only one button can be clicked at a time).
It seems that whenever I click one button to update the index (and change the color of the button), the main widget's Build method is called, along with the items in my list.
However, when using just a Consumer widget inside the itemBuilder method of my ListView, clicking one button no longer triggers the build method of the main widget.
So, is it considered a good practice to just use Consumer widgets where needed?
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.
I have an app with a bunch of text views inside a form. When the form scrolls, I lose the text entered in the above text fields. I would like to preserve those values. I tried adding a controller and assigning the value to a variable inside the state class but it does not work.
P.S not just widgets, but almost every type of input for example drop down buttons, radio buttons and what not.
I had a bunch of small forms inside a list view. Turns out, scrolling far enough, destroys the forms not visible to the user destroying their state. I need to lift their state up to the parent widget. For more information on how to do that, check how to keep the state of my widgets after scrolling?
I am new to Flutter and reactive programming is also new thing for me.
Let's say I want to build a timer with Flutter.
I add a Scaffold with all the necessary stuff in it and I add a IconButton which starts the Stopwatch and Text which displays elapsed time. I also add Timer.periodic to periodically (every 0.5 second) update the text.
Text Widget controls it's own state by checking if Stopwatch is running and updating it's values.
So now let's say I want to have more complicated logic that changes the text based on some actions with other buttons which are the siblings of Text. However it is not possible to call setState of Text widget directly from sibling widgets. As I understand the point of reactive paradigm is that the state can be passed down the Tree. However if I make my Scaffold as StatefulWidget and update the state of the parent every 0.5 second it will redraw my entire Scaffold with all it's children. So eventually when the Scaffold gets big enough it will have to update everything instead of single Text widget.
Am I correct? And is there any solution to this. I read something about Streams and Sinks however it looks very complicated and I think that there should be another solution.
You don't need to rebuild the whole tree, if the state only changed in a sub widget, ideally you want to call set state in that widget so only that part of the tree (the one whose state changed) is rebuilt.
Streams aren't really that complicated, it's a good way for you to send messages between different components in your app, which is what you're trying to do here.
In your case you can also use a ValueNotifier to store state in the parent widget, or maybe an AnimationController, and send its listener down to the sub widget that needs be updated on change.
In any case, the state is lifted to a parent widget, which then becomes accessible to the sub widget through a listener, or a stream. When the listener triggers a signal, you rebuild the sub widget only.
Extract out widget and call setState() form that widget and it's don't render all the widget again