Override widget changing child widget in flutter

Issue

Basically I have two buttons widget that looks the same, the only difference is that one is with icon and the other not.

This is my widget class with icon

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

And this is without it

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

I think that there should be a way in order to not repeat the code twice. I just want to change the child from TextButton.icon to TextButton.

any ideas?

Solution

You can create a single class with the icon field being optional. Then if the icon field is not null, use the TextButton.icon else use the TextButton.

Consider the following code

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

We can save the label and style to separate variables to avoid duplication.
Check whether the icon is null and use the TextButton.icon or TextButton.

Answered By – Arjunraj kokkadan

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *