Flutter 颤振:如何从现有小部件正确创建自定义小部件并使用其属性(有时是有条件的)
我正在尝试创建一个与现有小部件几乎相同的小部件。这意味着,如果我想使用现有小部件的属性,我必须将它们从我的自定义小部件传递给它。在本例中,我将创建一个包含文本字段的小部件。我的方法是:Flutter 颤振:如何从现有小部件正确创建自定义小部件并使用其属性(有时是有条件的),flutter,Flutter,我正在尝试创建一个与现有小部件几乎相同的小部件。这意味着,如果我想使用现有小部件的属性,我必须将它们从我的自定义小部件传递给它。在本例中,我将创建一个包含文本字段的小部件。我的方法是: class MyTextFieldWithPadding extends StatelessWidget { final Function onTap; final ValueSetter<String> onChanged; final TextEditingController co
class MyTextFieldWithPadding extends StatelessWidget {
final Function onTap;
final ValueSetter<String> onChanged;
final TextEditingController controller;
final double padding;
MyTextFieldWithPadding({this.controller, this.onTap, this.onChanged, this.padding});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(padding),
child: TextField(
onTap: onTap,
onChanged: onChanged,
controller: controller,
)
);
}
}
如果我没有使用所有的属性,我总是会得到异常,因为,是的,它们是空的
以下NoSuchMethodError在生成时抛出
MyTextFieldWithPadding:对null调用了方法“>=”。接收人:
null尝试调用:>=(0.0)
等等
也许有其他方法可以创建一个小部件,如果你能给我一些反馈,我将非常感谢 在您的示例中,未设置
padding
属性,这将导致您看到的错误。若要在未设置字段的情况下设置特定默认值,可以将其更改为:
class MyTextFieldWithPadding扩展了无状态小部件{
最终功能onTap;
最终价值设定人一经变更;
最终文本编辑控制器;
最终双重填充;
MyTextFieldWithPadding(
{this.controller,this.onTap,this.onChanged,double padding})
:padding=padding±0;
@凌驾
小部件构建(构建上下文){
返回填充(
填充:边缘集。全部(填充),
孩子:TextField(
onTap:onTap,
一旦改变:一旦改变,
控制器:控制器,
));
}
}
看看
TextField
小部件的实现,您将看到同样的事情,包括如何为某些属性断言特定值。在您的示例中,没有设置padding
属性,这会导致您看到的错误。若要在未设置字段的情况下设置特定默认值,可以将其更改为:
class MyTextFieldWithPadding扩展了无状态小部件{
最终功能onTap;
最终价值设定人一经变更;
最终文本编辑控制器;
最终双重填充;
MyTextFieldWithPadding(
{this.controller,this.onTap,this.onChanged,double padding})
:padding=padding±0;
@凌驾
小部件构建(构建上下文){
返回填充(
填充:边缘集。全部(填充),
孩子:TextField(
onTap:onTap,
一旦改变:一旦改变,
控制器:控制器,
));
}
}
看看TextField
小部件的实现,您将看到同样的事情,包括如何为某些属性断言特定值。解决方案1:参数列表中的默认值
虽然更加惯用,但如果嵌套自定义小部件,则必须在任何地方定义默认值
例如:
class MyOtherWidget extends StatelessWidget {
final double padding;
MyOtherWidget({Key key, this.padding = 10.0}) : super(key: key);
@override
Widget build(BuildContext context) {
return MyTextFieldWithPadding(padding: padding);
}
}
如果不这样做,则MyTextFieldWithPadding
中的填充将为空
因此,如果您嵌套自定义小部件,那么最好
解决方案2:初始化为默认值
无需到处定义默认值。如果为空,将使用默认值
旁注:回调方法
onPressed
只有在参数列表中的默认值不是null
时才会调用回调
虽然更加惯用,但如果嵌套自定义小部件,则必须在任何地方定义默认值
例如:
class MyOtherWidget extends StatelessWidget {
final double padding;
MyOtherWidget({Key key, this.padding = 10.0}) : super(key: key);
@override
Widget build(BuildContext context) {
return MyTextFieldWithPadding(padding: padding);
}
}
如果不这样做,则MyTextFieldWithPadding
中的填充将为空
因此,如果您嵌套自定义小部件,那么最好
解决方案2:初始化为默认值
无需到处定义默认值。如果为空,将使用默认值
旁注:回调方法
onPressed
callback只有在它不是null
时才会被调用。这种提供填充的方法太过分了。在参数列表中执行双填充=0
会更为惯用。谢谢@Tim Klingelers的回答。如果你愿意,请检查上面的注释,我在这里添加了另一个例外情况。这种提供填充的方法太过分了。在参数列表中执行双填充=0
会更为惯用。谢谢@Tim Klingelers的回答。如果你愿意的话,请检查上面的评论,在那里我添加了另一个例外情况。伙计,那个填充的东西是一个非常明显的错误。我不会为了帮助其他经历过这种事情的人而纠正它。然而,旁注是非常有用的。我会检查你的笔记,谢谢。但是,我必须说,如果我在我的主小部件中有cursorWidth
作为最后一个变量,并且在嵌套的小部件中也有它,比如:cursorWidth
:cursorWidth
,但没有给它赋值,那将抛出一个平均值,例如失败的断言:第247行第15位:“cursorWidth!”null&&cursorWidth>=0.0”:不正确。
您将如何处理此问题。你会一直验证这些东西还是给它们分配一个默认值?伙计,那个填充的东西是一个非常明显的错误。我不会为了帮助其他经历过这种事情的人而纠正它。然而,旁注是非常有用的。我会检查你的笔记,谢谢。但是,我必须说,如果我在我的主小部件中有cursorWidth
作为最后一个变量,并且在嵌套的小部件中也有它,比如:cursorWidth
:cursorWidth
,但没有给它赋值,那将抛出一个平均值,例如失败的断言:第247行第15位:“cursorWidth!”null&&cursorWidth>=0.0”:不正确。
您将如何处理此问题。您是否总是验证这些内容或为它们指定默认值?
class MyOtherWidget extends StatelessWidget {
final double padding;
MyOtherWidget({Key key, this.padding = 10.0}) : super(key: key);
@override
Widget build(BuildContext context) {
return MyTextFieldWithPadding(padding: padding);
}
}
class MyTextFieldWithPadding extends StatelessWidget {
final double _padding;
MyTextFieldWithPadding({Key key, padding}) :
_padding = padding ?? 10.0,
super(key: key);
}
class MyCustomWidget extends StatelessWidget {
final String _label;
final VoidCallback onPressed;
MyTextFieldWithPadding({Key key, this.onPressed}) :
_label = label ?? 'CLICK',
super(key: key);
@override
Widget build(BuildContext context) {
return Elevated(
onPressed: () => onPressed?.call(),
child: Text(_label),
);
}
}