Reputation: 17169
When using the following Switch
widget, the isOn
value always returns true
and never changes.
The Switch
only moves position on a swipe too, a tap won't move it. How to resolve?
bool isInstructionView = false;
Switch(
value: isInstructionView,
onChanged: (bool isOn) {
setState(() {
isInstructionView = isOn;
print(isInstructionView);
});
},
activeColor: Colors.blue,
inactiveTrackColor: Colors.grey,
inactiveThumbColor: Colors.grey,
)
Update: For extra clarity, onChanged
always returns isOn
as true
. Why would this be?
Upvotes: 16
Views: 28819
Reputation: 91
I faced the same issue , the problem is your
bool isInstructionView = false;
is in same build method which will get rebuild due to change of switch to render new UI on setState()
Solution is to move it out of function Scope to Class Scope so that your variable do not change on rendering Widget again
Upvotes: 4
Reputation: 41
Use Transform when use Switch will work.
bool isSwitched = false;
Transform.scale(
scale: 1.8,
child: Switch(
onChanged: (value) {
setState(() {
isSwitched = value;
});
},
value: isSwitched,
),
)
Upvotes: 1
Reputation: 41
Change SwitchListTile instead of Switch will work.
bool isSwitched = false;
SwitchListTile(
title: Text("title"),
controlAffinity: ListTileControlAffinity.leading,
contentPadding: EdgeInsets.symmetric(),
value: isSwitched ,
onChanged: (bool value) {
setState(() {
isSwitched = value;
});
}
)
Upvotes: 2
Reputation: 1539
To get Switch to work , move the setState(() {}) outside of Switch in a callback function
.
// Switch Widget
Switch( value: _toggleState,
onChanged: _attemptChange,
),
//Callback
void _attemptChange(bool newState) {
setState(() {
_toggleState = newState;
newState ? _switchCase = 'ON' : _switchCase = 'OFF';
});
Upvotes: 1
Reputation: 337
Here Is my code for toggle button
class ToggleButtonScreen extends StatefulWidget {
@override
_ToggleButtonScreenState createState() => _ToggleButtonScreenState();
}
class _ToggleButtonScreenState extends State<ToggleButtonScreen> {
bool _value = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: _value ? AssetImage("images/cnw.png") : AssetImage("images/cnw.png"),
fit: BoxFit.cover,
),
),
child: Padding(
padding: EdgeInsets.all(AppDimens.EDGE_REGULAR),
child: Column(
children: [
// _customSwitchButton(),
_normalToggleButton(),
],
),
),
),
),
),
);
}
Widget _normalToggleButton () {
return Container(
child: Transform.scale(
scale: 2.0,
child: Switch(
activeColor : Colors.greenAccent,
inactiveThumbColor: Colors.redAccent,
value: _value,
activeThumbImage: AssetImage("images/cnw.png"),
inactiveThumbImage : AssetImage("images/simple_interest.png"),
onChanged: (bool value){
setState(() {
_value = value;
});
},
),
),
);
}
}
Upvotes: 4
Reputation: 169
You just need to make sure to declare the bool for the switch toggle outside Widget build to make it global and acessible for SetState method. No need to initstate and etc.
class ExampleClass extends StatefulWidget {
@override
_ExampleClassState createState() => _ExampleClassState();
}
class _ExampleClassState extends State<ExampleClass> {
bool isInstructionView = false;
@override
Widget build(BuildContext context) {
return Container(
child: Switch(
value: isInstructionView,
onChanged: (isOn) {
setState(() {
isInstructionView = isOn
});
print(isInstructionView);
},
...
),
);
}
}
Upvotes: 11
Reputation: 686
I have also got the same problem while I was implementing CupertinoSwitch. I was able to turn it ON but wasn't able to turn it OFF.
According to this example, I tried to put my Switch inside the widget called 'Semantics' and magically it started working.
Below is the code:
body: Column(
children: <Widget>[
SizedBox(height: 50.0,),
Semantics(
container: true,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
CupertinoSwitch(
value: _switchValue,
onChanged: (bool value){
setState(() {
_switchValue = value;
_animating = value;
});
},
),
Text(
"${_switchValue ? "On" : "Off"}",
style: TextStyle(fontSize: 20.0,
fontWeight: FontWeight.bold),
),
],
),
),
SizedBox(
height: 50.0,
),
Visibility(
child: CupertinoActivityIndicator(
animating: _animating,
radius: 30.0,
),
visible: _animating,
),
],
),
Hope it helps.
Upvotes: -1
Reputation: 262
You need to rebuild the widget when the state changes. refer the documentation https://docs.flutter.io/flutter/material/Switch/onChanged.html
Upvotes: 2
Reputation: 5943
I added additional code chunks according to @Zulfiqar 's answer. I didn't test this code but I m using similar codes in my project. if you want to save it and use in another class or if you want to show latest state for everytime you load you can save the state in a global variable and call it when you load the class. hope it will help..
class Tab_b extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _TabsPageState();
}
class _TabsPageState extends State<Tab_b>{
bool isInstructionView;
@override
void initState() {
isInstructionView = Global.shared.isInstructionView;
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text("add data"),
),
body: new Container(
child: Switch(
value: isInstructionView,
onChanged: (bool isOn) {
print(isOn);
setState(() {
isInstructionView = isOn;
Global.shared.isInstructionView = isOn;
isOn =!isOn;
print(isInstructionView);
});
},
activeColor: Colors.blue,
inactiveTrackColor: Colors.grey,
inactiveThumbColor: Colors.grey,
),
),
);
}
}
class Global{
static final shared =Global();
bool isInstructionView = false;
}
Upvotes: 8
Reputation: 5793
class Tab_b extends StatefulWidget {
bool isInstructionView = false;
@override
State<StatefulWidget> createState() => new _TabsPageState();
}
class _TabsPageState extends State<Tab_b>{
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text("add data"),
),
body: new Container(
child: Switch(
value: widget.isInstructionView,
onChanged: (bool isOn) {
print(isOn);
setState(() {
widget.isInstructionView = isOn;
print(widget.isInstructionView);
});
},
activeColor: Colors.blue,
inactiveTrackColor: Colors.grey,
inactiveThumbColor: Colors.grey,
),
),
);
}
Upvotes: 4