Reputation: 1988
In Android, every Fragment can partecipate in populating the options menu (aka "appBar actions", in flutter terms) of the activity, using the Fragment.onCreateOptionsMenu
callback.
I would like a similar mechanism also in flutter, i.e. that some widgets are able to add buttons ("actions") to the AppBar.
Threads had already been opened on this topic, but none reports a fully functional example and contains solutions to the precise technical problem I encountered.
To do this, I had thought of using the following 'typical' structure:
a StatefulWidget -to which I have given name ScaffoldHandler
(ScaffoldHandlerWidget/ScaffoldHandlerState
)- which wraps the entire Scaffold, and which uses InheritedWidget so that widgets further down the widgets tree can get a reference to it in an optimal way (using the classic of()
method which executes dependOnInheritedWidgetOfExactType()
).
ScaffoldHandlerState keeps in a field the actions set by the various children, and supplies them to the app-bar.
a widget that creates the AppBar. In the build()
method it gets the actions to be displayed calling ScaffoldHandlerState.of()
.
mixin ScaffoldChild on State
, which applied to a widget gives it the ability to add actions to ScaffoldHandlerState
.
Internally, ScaffoldChild executes ScaffoldHandlerState.of()
in didChangeDependencies()
(to add actions) and in deactivate()
(to remove them).
I originally used initState()
and dispose()
but this did not handle the case where a ScaffoldChild changes position while not being permanently removed from the widgets tree.
The problem I encountered is that ScaffoldAppBar.build
is executed before ScaffoldChild.didChangeDependencies
, so when the app-bar is created, ScaffoldChild still has to put its actions in ScaffoldHandlerState.
The curious thing is that this problem is due to the simple linear order in which ScaffoldAppBar and ScaffoldChild are inserted in the page: if instead of a top app-bar I want to create a bottom app-bar, the problem is not there because ScaffoldChild.didChangeDependencies
would run before ScaffoldAppBar.build
.
As a workaround to overcome the problem, I have inserted in ScaffoldChild.didChangeDependencies
a call to scaffoldHandler.setState
scheduled by WidgetsBinding.instance.addPostFrameCallback()
: thus, after the actions have been inserted in ScaffoldHandler, the app-bar is updated with the new actions.
However, this solution seems like a hack to me.
In stackoverflow I see a lot of problems solved with addPostFrameCallback + setState
, and sometimes that solution avoids really understanding where it goes wrong; I am interested in understanding if there are better solutions because my purpose, as well as practical, was to better understand the lifecycle of widgets.
Is there a better solution?
This is my code:
(I tried to shorten it as much as possible, but sorry if it's not really short)
Upvotes: 1
Views: 139