Я новичок во Флаттере, и я преодолел свой первый контрольно-пропускной пункт, пытаясь сделать собственный переключатель. Мой переключатель должен функционировать так же, как фактический Switch
из библиотеки материалов, единственное отличие - это пользовательский интерфейс.
Я использую ValueNotifier
и ValueListenableBuilder
для обновления значения переключателя из другого виджета , Вот соответствующие части моего кода:
Содержащий виджет
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;
});
},
);
}
}
Виджет, который изменяет значение переключателя
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(...),
),
);
}
}
Пользовательский переключатель
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);
});
}
}
Если я звоню _toggle()
из CustomSwitch
, переключатель будет прекрасно переключаться с анимацией (я использую AnimatedPositioned
для переключатель). Это прекрасно работает, если я полагаюсь только на пользовательский ввод, но мне нужно также программно переключать переключатель, и я чувствую, что мне чего-то не хватает, хотя c и все же я в замешательстве.
Мое текущее понимание в том, что CustomSwitch
будет перестраиваться каждый раз, когда я изменяю его значение с ChildWidget
, потому что я использую значение переключателя как Key
, но как это сделать с анимацией, как если бы я звонил _toggle()
после того, как он был построен?
Как и в Java, вы обычно делаете что-то вроде customSwitch.toggle()
.