Flutter flatter如何在自定义小部件中以编程方式调用方法?
我是一个新手,在尝试进行自定义切换时遇到了第一个障碍。我的开关在功能上应该与材质库中实际的Flutter flatter如何在自定义小部件中以编程方式调用方法?,flutter,dart,widget,custom-widgets,Flutter,Dart,Widget,Custom Widgets,我是一个新手,在尝试进行自定义切换时遇到了第一个障碍。我的开关在功能上应该与材质库中实际的开关相同,唯一的区别是UI 我正在使用ValueNotifier和ValueListenableBuilder从另一个小部件更新开关值。以下是我的代码的相关部分: 包含小部件 class ParentWidget extends StatefulWidget { @override _ParentWidget createState() => _ParentWidget(); } c
开关
相同,唯一的区别是UI
我正在使用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;
});
},
);
}
}
类ParentWidget扩展StatefulWidget{
@凌驾
_ParentWidget createState()=>\u ParentWidget();
}
类_ParentWidgetState扩展状态{
ValueNotifier\u switchNotifier=ValueNotifier(假);
@凌驾
小部件构建(构建上下文){
返回容器(
子项:ValueListenableBuilder(
valueListenable:\u switchNotifier,
生成器:(上下文、开关值、子项){
返回_buildSwitch(switchValue);
},
),
);
}
小部件构建开关(布尔开关值){
返回自定义开关(
key:key(value.toString()),
initValue:switchValue,
一旦更改:(值){
设置状态(){
_switchNotifier.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-ChildWidget扩展了StatefulWidget{
最终价值通知人(开关通知人);;
ChildWidget(此._switchNotifier);
@凌驾
_ChildWidgetState createState()=>\u ChildWidgetState();
}
类_ChildWidgetState扩展状态{
@凌驾
小部件构建(构建上下文){
返回容器(
儿童:手势检测器(
onTap:(){
widget.\u switchNotifier.value=false;
},
子:图像(…),
),
);
}
}
自定义开关
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);
});
}
}
class CustomSwitch扩展StatefulWidget{
变更后的最终价值;
最终布尔初始值;
最后一键;
常数自定义开关({
@需要这个.key,
一旦改变了,
这个.initValue,
});
@凌驾
_CustomSwitchState createState()=>\u CustomSwitchState();
}
类_CustomSwitchState扩展状态{
布尔值;
@凌驾
void initState(){
value=widget.initValue;
super.initState();
}
@凌驾
小部件构建(构建上下文){
//开关/切换与材质开关一样设置动画
返回开关(…);
}
_切换(){
设置状态(){
value=!value;
widget.onChanged(值);
});
}
}
如果我从CustomSwitch
调用\u toggle()
,该开关将很好地与动画切换(我使用AnimatedPositioned
作为开关)。如果我只依赖于用户输入,这很好,但我还需要通过编程切换开关,我觉得我缺少了一些基本的东西,但我被难倒了
我目前的理解是,每次我从ChildWidget
更改其值时,CustomSwitch
都会重新生成,因为我将开关值用作键
,但如何在创建后调用\u toggle()
像在Java中一样,您通常会执行类似于customSwitch.toggle()
的操作,大多数颤振小部件使用控制器来与外部小部件进行交互(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();
}
}
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);
}
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
);
}
您需要接受自定义控制器作为CustomWidget中的参数,并将其传递到其状态,如下所示:
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();
}
}
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);
}
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
);
}
在自定义类的状态中,将使用我们创建的addState方法将类的状态分配给控制器。您可以通过以下方式使用构造函数执行此操作:
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();
}
}
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);
}
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()
来切换值!
这就是本机小部件让您与它们交互的方式