Duncan Jones
Duncan Jones

Reputation: 69399

Allow a row child to expand if necessary, but otherwise occupy minimum size

I wrote a Flutter package that provides sign in buttons for social platforms. Here's an example of what one looks like:

Button image

I'm struggling to get this button to look nice when a parent makes it stretch. For example, placing this button in a column with CrossAxisAlignment.stretch. I would like the icon and text to remain as they are, and the spare space 'added' to the blue on the right hand side.

As you can see from the code, this is a RaisedButton with an Icon and Text, plus some padding (as defined by Google's standards). It uses a Row with MainAxisSize.min:

    // Code omitted for clarity (see link above for full version)
    ButtonTheme(
      child: RaisedButton(
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(1.0),
              child: Container(
                height: 38.0, 
                width: 38.0,
                child: Center(
                  child: Image(...),
                    height: 18.0,
                    width: 18.0,
                  ),
                ),
              ),
            ),

            SizedBox(width: 14.0),
            Padding(
              padding: const EdgeInsets.fromLTRB(0.0, 8.0, 8.0, 8.0),
              child: Text("Sign in with Google"),
            ),
          ],
        ),
      ),
    );

I tried adding a Spacer to the row as the final widget, but that causes the row to always expand to fill its parent. Instead, I want it to only fill the parent when the parent forces it to.

Any suggestions for how to tackle this?

Upvotes: 1

Views: 436

Answers (1)

diegoveloper
diegoveloper

Reputation: 103541

You can use the Align widget as a parent of your RaisedButton , something like this :

         child: Align(
                alignment: Alignment.centerLeft,
                child: RaisedButton(
                  onPressed: onPressed,
                  color: darkMode ? Color(0xFF4285F4) : Colors.white,
                  child: Row(
                    mainAxisSize: MainAxisSize.min,

Using this , your Row won't expand :)

OR

Use LayoutBuilder if you want to expand the button according the parent widget :

         @override
          Widget build(BuildContext context) {
            return LayoutBuilder(
              builder: (context, constraints) {
                return ButtonTheme(
                  height: 40.0,
                  padding: const EdgeInsets.all(0.0),
                  shape: RoundedRectangleBorder(
                    // Google doesn't specify a border radius, but this looks about right.
                    borderRadius: BorderRadius.circular(3.0),
                  ),
                  child: Align(
                    alignment: Alignment.centerLeft,
                    child: RaisedButton(
                      onPressed: onPressed,
                      color: darkMode ? Color(0xFF4285F4) : Colors.white,
                      child: Row(
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          // The Google design guidelines aren't consistent. The dark mode
                          // seems to have a perfect square of white around the logo, with a
                          // thin 1dp (ish) border. However, since the height of the button
                          // is 40dp and the logo is 18dp, it suggests the bottom and top
                          // padding is (40 - 18) * 0.5 = 11. That's 10dp once we account for
                          // the thin border.
                          //
                          // The design guidelines suggest 8dp padding to the left of the
                          // logo, which doesn't allow us to center the image (given the 10dp
                          // above). Something needs to give - either the 8dp is wrong or the
                          // 40dp should be 36dp. I've opted to increase left padding to 10dp.
                          Padding(
                            padding: const EdgeInsets.all(1.0),
                            child: Container(
                              height: 38.0, // 40dp - 2*1dp border
                              width: 38.0, // matches above
                              decoration: BoxDecoration(
                                color: Colors.white,
                                borderRadius: BorderRadius.circular(3.0),
                              ),
                              child: Center(
                                child: Image(
                                  image: AssetImage(
                                    "graphics/google-logo.png",
                                    package: "flutter_auth_buttons",
                                  ),
                                  height: 18.0,
                                  width: 18.0,
                                ),
                              ),
                            ),
                          ),

                          SizedBox(width: 14.0 /* 24.0 - 10dp padding */),
                          Padding(
                            padding: const EdgeInsets.fromLTRB(0.0, 8.0, 8.0, 8.0),
                            child: Text(
                              text,
                              style: TextStyle(
                                fontSize: 18.0,
                                fontFamily: "Roboto",
                                fontWeight: FontWeight.w500,
                                color: darkMode
                                    ? Colors.white
                                    : Colors.black.withOpacity(0.54),
                              ),
                            ),
                          ),
                          constraints.minWidth == 0 ? SizedBox.shrink() : Spacer(),
                        ],
                      ),
                    ),
                  ),
                );
              },
            );
          }

Upvotes: 2

Related Questions