问题
I'm looking for a way to hide/change appBar actions when specific tab from tabBar is pressed.
Calling setState(() { })
method redrawing entire widget and so all the TabController children/screens, which is real bad.
Below is my code:
enum SelectedTab {
items, sales, raw_items, orders
}
class _MyHomePageState extends State<MyHomePage>
{
Widget rightActionButton(BuildContext context)
{
//This is the widget which is expected to be update upon tab change
SelectedTab currentTab = Globals.instance.selectedTab;
return Visibility (
child: . . .
visible: currentTab != SelectedTab.sales,
);
}
Widget navBar(BuildContext context)
{
return AppBar(
title: Text('Example'),
actions: <Widget>[
rightActionButton(context),
],
);
}
Widget tabBar(BuildContext context)
{
return Container(
child: TabBar(
tabs: [
. . . .
],
onTap: (index) {
Globals.instance.selectedTab = SelectedTab.values[index];
//Refresh rightActionButton
},
),
);
}
Widget tabScreens(BuildContext context) {
return TabBarView(
children: [
. . . .
],
);
}
@override
Widget build(BuildContext context)
{
return DefaultTabController(
length: 4,
child: Scaffold (
appBar: navBar(context),
bottomSheet: tabBar(context),
body: tabScreens(context),
),
);
}
}
How can we redraw actions of the appBar only
instead of redrawing all the widgets in scaffold ?
回答1:
In Flutter, when you call setState()
, it will automatically track which widgets depend on the data that was changed in setState()
function and rebuilds the parts of your tree that have changed, not the whole widget.
So, don't worry about the redrawing of the widget tree, the Flutter team took care of that.
回答2:
Answering my own question:
The fact is we require to call setState((){}) on StatefulWidget in order for it to redraw. So I just moved the code from Widget rightActionButton()
to separate class extends from StatefulWidget.
class ActionButton extends StatefulWidget
{
final ActionButtonState abs = ActionButtonState();
void refresh() {
abs.refresh();
}
@override
ActionButtonState createState() => abs;
}
class ActionButtonState extends State<ActionButton>
{
void refresh() {
setState(() {});
}
@override
Widget build(BuildContext context)
{
SelectedTab currentTab = Globals.instance.selectedTab;
return Visibility ( ... )
}
}
And then we can just call refresh() method of ActionButton instance wherever its used. Like:
class _MyHomePageState extends State<MyHomePage>
{
ActionButton actionButton1 = new ActionButton();
Widget navBar(BuildContext context)
{
return AppBar(
title: Text('Example'),
actions: <Widget>[
actionButton1,
],
);
}
Widget tabBar(BuildContext context)
{
return Container(
child: TabBar(
tabs: [
. . . .
],
onTap: (index) {
Globals.instance.selectedTab = SelectedTab.values[index];
actionButton1.refresh();
},
),
);
}
.
.
}
来源:https://stackoverflow.com/questions/58791044/hot-to-refresh-actions-of-appbar-on-tab-change