I'm new to Flutter and I've hit my first roadblock while trying to make a custom switch. My switch should functionally work the same like the actual Switch
from the material library, the only difference is the UI.
I'm using ValueNotifier
and ValueListenableBuilder
to update the switch value from another widget. Here's the relevant parts of my code:
Containing Widget
class ParentWidget extends StatefulWidget {
@override
_ParentWidget createState() => _ParentWidget();
}
class _ParentWidgetState extends State<ParentWidget> {
ValueNotifier _switchNotifier = ValueNotifier(false);
@override
Widget build(BuildContext context) {
return Container(
child: ValueListenableBuilder(
valueListenable: _switchNotifier,
builder: (context, switchValue, child) {
return _buildSwitch(switchValue);
},
),
);
}
Widget _buildSwitch(bool switchValue) {
return CustomSwitch(
key: Key(value.toString()),
initValue: switchValue,
onChanged: (value) {
setState(() {
_switchNotifier.value = value;
});
},
);
}
}
The widget that changes the switch value
class ChildWidget extends StatefulWidget {
final ValueNotifier _switchNotifier;
ChildWidget(this._switchNotifier);
@override
_ChildWidgetState createState() => _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
@override
Widget build(BuildContext context) {
return Container(
child: GestureDetector(
onTap: () {
widget._switchNotifier.value = false;
},
child: Image(...),
),
);
}
}
Custom Switch
class CustomSwitch extends StatefulWidget {
final ValueChanged<bool> onChanged;
final bool initValue;
final Key key;
const CustomSwitch({
@required this.key,
this.onChanged,
this.initValue,
});
@override
_CustomSwitchState createState() => _CustomSwitchState();
}
class _CustomSwitchState extends State<CustomSwitch> {
bool value;
@override
void initState() {
value = widget.initValue;
super.initState();
}
@override
Widget build(BuildContext context) {
// the switch/toggle is animated just like the Material Switch
return TheSwitch(...);
}
_toggle() {
setState(() {
value = !value;
widget.onChanged(value);
});
}
}
If I'm calling _toggle()
from the CustomSwitch
the switch would toggle nicely with animation (I'm using AnimatedPositioned
for the switch). This works fine if I'm only relying on user input, but I need to also programmatically toggle the switch and I feel like I'm missing something basic yet I'm stumped.
My current understanding is that the CustomSwitch
would be rebuilt every time I change its value from ChildWidget
because I'm using the switch value as a Key
, but how to do it nicely with animation as if I'm calling _toggle()
after it has been built?
Like in Java you'd usually do something like customSwitch.toggle()
.