Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 颤振:如何从现有小部件正确创建自定义小部件并使用其属性(有时是有条件的)_Flutter - Fatal编程技术网

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),
    );
  }
}