Reputation: 215
What I want is when I click the switch button, the text in the Option1Content
widget should change to true or false (depending upon the current value of the switch). The value is correct when you click the tile, select a different option from the drawer, and then come back to option 1, you will have the correct value. My requirement is when I press the switch tile the value of Option1Content
should change instantly. For functionality reference: https://dartpad.dev/c9cabc35a0bda57758b1d1cf07f8a823. Any help would be greatly appreciated. Thank you.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyWidget(),
);
}
}
class MyWidget extends StatefulWidget{
MyWidgetState createState()=> MyWidgetState();
}
class MyWidgetState extends State<MyWidget> {
bool status;
Widget myBody;
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
void closeDrawer() {
if (_scaffoldKey.currentState.isDrawerOpen) {
_scaffoldKey.currentState.openEndDrawer();
}
}
@override
void initState(){
super.initState();
status = false;
myBody = Option1Content(status:status);
}
@override
Widget build(BuildContext context) {
return Scaffold(
key:_scaffoldKey,
appBar:AppBar(
iconTheme: IconThemeData(color: Colors.black),
elevation:0,
backgroundColor:Colors.transparent,
actions:[
Switch(
inactiveThumbColor: Colors.black,
activeColor: Colors.green,
value:status,
onChanged:(value){
setState((){
status=value;
});
})
]
),
drawer: Drawer(
child:Center(child:ListView(children:[
DrawerHeader(
child: Column(
children: <Widget>[
CircleAvatar(
radius: 50,
backgroundColor: Colors.grey,
),
Padding(
padding: const EdgeInsets.only(
left: 8.0, right: 8.0, top: 12.0),
child: Text(
'Account',
style: TextStyle(
fontWeight: FontWeight.bold,
),
textScaleFactor: 1.3,
),
),
],
),
),
ListTile(title:Center(child:Text('Option 1')),onTap:(){
closeDrawer();
setState((){
myBody = Option1Content(status:status);
});
}),
ListTile(title:Center(child:Text('Option 2')),onTap:(){
closeDrawer();
setState((){
myBody = Center(child:Text('Option 2 Content'));
});
}),
ListTile(title:Center(child:Text('Option 3')),onTap:(){
closeDrawer();
setState((){
myBody = Center(child:Text('Option 3 Content'));
});
}),
]))
),
body: myBody
);
}
}
class Option1Content extends StatefulWidget {
final bool status;
Option1Content({@required this.status});
@override
_Option1ContentState createState() => _Option1ContentState();
}
class _Option1ContentState extends State<Option1Content> {
@override
Widget build(BuildContext context) {
return Center(
child: Text('${widget.status}'),
);
}
}
Upvotes: 1
Views: 143
Reputation: 17113
The issue is that simply changing the value of status doesn't update what is actually in myBody
, which is what's shown. Even when changing status
with setState
, myBody
still contains your widget with the old value of status
. This is why when you go to another myBody
and come back, it's updated, because myBody
now has the new widget with the updated status
value.
To solve this you need to have a method of updating what's contained in myBody
, because that's the only part that's being built. Doing the following is the simplest change.
Just change
setState((){
status = value;
});
to
setState((){
status = value;
myBody = Option1Content(status:status);
});
and the full code:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyWidget(),
);
}
}
class MyWidget extends StatefulWidget{
MyWidgetState createState()=> MyWidgetState();
}
class MyWidgetState extends State<MyWidget> {
bool status;
Widget myBody;
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
void closeDrawer() {
if (_scaffoldKey.currentState.isDrawerOpen) {
_scaffoldKey.currentState.openEndDrawer();
}
}
@override
void initState(){
super.initState();
status = false;
myBody = Option1Content(status:status);
}
@override
Widget build(BuildContext context) {
return Scaffold(
key:_scaffoldKey,
appBar:AppBar(
iconTheme: IconThemeData(color: Colors.black),
elevation:0,
backgroundColor:Colors.transparent,
actions:[
Switch(
inactiveThumbColor: Colors.black,
activeColor: Colors.green,
value:status,
onChanged:(value){
setState((){
status = value;
myBody = Option1Content(status:status);
});
})
]
),
drawer: Drawer(
child:Center(child:ListView(children:[
DrawerHeader(
child: Column(
children: <Widget>[
CircleAvatar(
radius: 50,
backgroundColor: Colors.grey,
),
Padding(
padding: const EdgeInsets.only(
left: 8.0, right: 8.0, top: 12.0),
child: Text(
'Account',
style: TextStyle(
fontWeight: FontWeight.bold,
),
textScaleFactor: 1.3,
),
),
],
),
),
ListTile(title:Center(child:Text('Option 1')),onTap:(){
closeDrawer();
setState((){
myBody = Option1Content(status:status);
});
}),
ListTile(title:Center(child:Text('Option 2')),onTap:(){
closeDrawer();
setState((){
myBody = Center(child:Text('Option 2 Content'));
});
}),
ListTile(title:Center(child:Text('Option 3')),onTap:(){
closeDrawer();
setState((){
myBody = Center(child:Text('Option 3 Content'));
});
}),
]))
),
body: myBody
);
}
}
class Option1Content extends StatefulWidget {
final bool status;
Option1Content({@required this.status});
@override
_Option1ContentState createState() => _Option1ContentState();
}
class _Option1ContentState extends State<Option1Content> {
@override
Widget build(BuildContext context) {
return Center(
child: Text('${widget.status}'),
);
}
}
Upvotes: 2