[英]Flutter how to programmatically call method in custom widget?
我是 Flutter 的新手,在尝试进行自定义切换时遇到了第一个障碍。 我的开关在功能上应该和材质库中的实际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);
});
}
}
如果我从CustomSwitch
调用_toggle()
开关会很好地切换动画(我使用AnimatedPositioned
作为开关)。 如果我只依赖用户输入,这很好用,但我还需要以编程方式切换开关,我觉得我错过了一些基本的东西,但我很难过。
我目前的理解是每次我从ChildWidget
更改它的值时都会重建CustomSwitch
,因为我使用 switch 值作为Key
,但是如何用动画很好地做到这一点,就像我在调用_toggle()
之后一样已建成?
就像在 Java 中一样,您通常会执行customSwitch.toggle()
。
大多数 flutter 小部件使用控制器与外部小部件进行交互(TextFormField、ListView 等)。
您的问题最简单的解决方案也是创建自定义控制器。
首先,您将创建一个控制器类,它将您的自定义小部件的状态作为参数。 此类还将公开您的小部件的方法。它看起来像这样:
class CustomWidgetController{
_CustomWidgetState _customWidgetState;
void _addState(_CustomWidgetState customWidgetState){
this._customWidgetState = customWidgetState;
}
/// Determine if the CustomWidgetController is attached to an instance
/// of the CustomWidget (this property must return true before any other
/// functions can be used)
bool get isAttached => _customWidgetState != null;
/// Here is the method you are exposing
void toggle() {
assert(isAttached, "CustomWidgetController must be attached to a CustomWidget");
_customWidgetState.toggle();
}
}
您需要在 CustomWidget 中接受自定义控制器作为参数,并将其传递到其状态,如下所示:
class CustomSwitch extends StatefulWidget {
final CustomWidgetController customWidgetController;
final bool initValue;
final Key key;
const CustomSwitch({
@required this.key,
this.customWidgetController,
this.initValue,
});
@override
_CustomSwitchState createState() => _CustomSwitchState(customWidgetController, initValue);
}
在自定义类的状态中,您将使用我们创建的 addState 方法将类的状态分配给控制器。 您可以像这样在构造函数中执行此操作:
class _CustomSwitchState extends State<CustomSwitch> {
final CustomWidgetController _customWidgetController;
bool value;
_CustomSwitchState(this._customWidgetController, this.value) {
if (_customWidgetController != null)
_customWidgetController._addState(this);
}
@override
Widget build(BuildContext context) {
// the switch/toggle is animated just like the Material Switch
return TheSwitch(...);
}
toggle() {
setState(() {
value = !value;
});
}
}
现在,您可以使用父小部件中的控制器传递控制器和调用方法,如下所示:
CustomWidgetController customWidgetController = new CustomWidgetController();
@override
Widget build(BuildContext context) {
return CustomWidget(
controller: customWidgetController,
initValue: true
);
}
就是这个! 现在您可以在代码中的任何位置调用customWidgetController.toggle()
来切换值! 这就是原生小部件让您与它们交互的方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.