在 flutter 中覆盖小部件更改 child 小部件

Override widget changing child widget in flutter

基本上我有两个看起来一样的按钮小部件,唯一的区别是一个有图标,另一个没有。

这是我的小部件class,带有图标

class ButtonElevationWithIcon extends StatelessWidget {
  final String buttonText;
  final Function onPressedButton;
  final Icon buttonIcon;
  final double height;

  ButtonElevationWithIcon(
      {@required this.buttonIcon,
      @required this.buttonText,
      this.height = 60,
      @required this.onPressedButton});

  @override
  Widget build(BuildContext context) {
    return Container(
        margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 40),
        decoration: ShapeDecoration(
          shape: StadiumBorder(
            side: BorderSide(width: 1.0),
          ),
          color: Colors.redAccent,
          shadows: <BoxShadow>[
            BoxShadow(
              color: Colors.redAccent.withOpacity(0.2),
              blurRadius: this.height / 5,
              offset: Offset(0, this.height / 10),
            ),
          ],
        ),
        child: TextButton.icon(
            label: Center(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Stack(
                  children: <Widget>[
                    Text(
                      this.buttonText,
                      style: TextStyle(
                        fontFamily: 'Poppins',
                        fontWeight: FontWeight.bold,
                        fontSize: Constants.kfontSizeButton,
                        letterSpacing: Constants.kletterSpacing,
                        color: Colors.yellowAccent,
                      ),
                    ),
                    Text(
                      this.buttonText,
                      style: TextStyle(
                        fontFamily: 'Poppins',
                        fontWeight: FontWeight.bold,
                        fontSize: Constants.kfontSizeButton,
                        letterSpacing: Constants.kletterSpacing,
                        foreground: Paint()
                          ..style = PaintingStyle.stroke
                          ..strokeWidth = 1.5
                          ..color = Colors.black,
                      ),
                    ),
                  ],
                ),
              ),
            ),
            icon: this.buttonIcon,
            style: ButtonStyle(
                foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
                backgroundColor:
                    MaterialStateProperty.all<Color>(Color(0xFFfa0002)),
                shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                    RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(40.0),
                ))),
            onPressed: onPressedButton));
  }
}

这是没有它的

class ButtonElevation extends StatelessWidget {
  final double height;

  final String buttonText;
  final Function onPressedButton;

  ButtonElevation(
      {@required this.buttonText,
      this.height = 100,
      @required this.onPressedButton});

  @override
  Widget build(BuildContext context) {
    return Container(
        margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 40),
        height: this.height,
        decoration: ShapeDecoration(
          shape: StadiumBorder(
            side: BorderSide(width: 1.0),
          ),
          color: Colors.redAccent,
          shadows: <BoxShadow>[
            BoxShadow(
              color: Colors.redAccent.withOpacity(0.2),
              blurRadius: this.height / 5,
              offset: Offset(0, this.height / 10),
            ),
          ],
        ),
        child: TextButton(
            child: Center(
              child: Stack(
                children: <Widget>[
                  Text(

                    this.buttonText,
                    style: TextStyle(
                      fontFamily: 'Poppins',
                      fontWeight: FontWeight.bold,
                      fontSize: Constants.kfontSizeButton,
                      letterSpacing: Constants.kletterSpacing,
                      color: Colors.yellowAccent,
                    ),
                  ),
                  Text(
                    this.buttonText,
                    style: TextStyle(
                      fontFamily: 'Poppins',
                      fontWeight: FontWeight.bold,
                      fontSize: Constants.kfontSizeButton,
                      letterSpacing: Constants.kletterSpacing,
                      foreground: Paint()
                        ..style = PaintingStyle.stroke
                        ..strokeWidth = 1.5
                        ..color = Colors.black,
                    ),
                  ),
                ],
              ),
            ),
            style: ButtonStyle(
                foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
                backgroundColor:
                    MaterialStateProperty.all<Color>(Color(0xFFfa0002)),
                shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                    RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(40.0),
                ))),
            onPressed: onPressedButton));
  }
}

我认为应该有一种方法可以不重复代码两次。我只想将 child 从 TextButton.icon 更改为 TextButton。

有什么想法吗?

尝试这样的事情:

class ButtonElevation extends StatelessWidget {
  final bool hasIcon;
  // Your other properties.

  ButtonElevation({
    this.hasIcon = true,
    // Your other properties.
  });

  @override
  Widget build(BuildContext context) {
    final child = RestOfYourWidget();
    return hasIcon ? TextButton.icon(label: child): TextButton(child: child);
  }
}

您可以创建一个 class,图标字段是可选的。然后如果图标字段不为空,则使用 TextButton.icon 否则使用 TextButton.

考虑以下代码

class ButtonElevationWithIcon extends StatelessWidget {
  final String buttonText;
  final Function onPressedButton;
  final Icon buttonIcon;
  final double height;

  ButtonElevationWithIcon(
      {this.buttonIcon,
      @required this.buttonText,
      this.height = 60,
      @required this.onPressedButton});

  Widget _label = Center(
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Stack(
                      children: <Widget>[
                        Text(
                          this.buttonText,
                          style: TextStyle(
                            fontFamily: 'Poppins',
                            fontWeight: FontWeight.bold,
                            fontSize: Constants.kfontSizeButton,
                            letterSpacing: Constants.kletterSpacing,
                            color: Colors.yellowAccent,
                          ),
                        ),
                        Text(
                          this.buttonText,
                          style: TextStyle(
                            fontFamily: 'Poppins',
                            fontWeight: FontWeight.bold,
                            fontSize: Constants.kfontSizeButton,
                            letterSpacing: Constants.kletterSpacing,
                            foreground: Paint()
                              ..style = PaintingStyle.stroke
                              ..strokeWidth = 1.5
                              ..color = Colors.black,
                          ),
                        ),
                      ],
                    ),
                  ),
                );

    ButtonStyle = ButtonStyle(
                    foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
                    backgroundColor:
                        MaterialStateProperty.all<Color>(Color(0xFFfa0002)),
                    shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                        RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(40.0),
                    ),
     ),
    );

  @override
  Widget build(BuildContext context) {
    return Container(
        margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 40),
        decoration: ShapeDecoration(
          shape: StadiumBorder(
            side: BorderSide(width: 1.0),
          ),
          color: Colors.redAccent,
          shadows: <BoxShadow>[
            BoxShadow(
              color: Colors.redAccent.withOpacity(0.2),
              blurRadius: this.height / 5,
              offset: Offset(0, this.height / 10),
            ),
          ],
        ),
        child: this.buttonIcon != null ? TextButton.icon(
            label: _label,
            icon: this.buttonIcon,
            style: _buttonStyle,
            onPressed: onPressedButton,
           ) : TextButton(
            label: _label,
            style: _buttonStyle,
            onPressed: onPressedButton,
           ),
          );
      }
    }

我们可以把labelstyle分开保存变量,避免重复。 检查 icon 是否为 null 并使用 TextButton.iconTextButton.