Разрешить дочерней строке при необходимости расширяться, но в остальном занимать минимальный размер

#flutter #flutter-layout

#flutter #флаттер-макет #flutter-layout

Вопрос:

Я написал пакет Flutter, который предоставляет кнопки входа для социальных платформ. Вот пример того, как это выглядит:

Изображение кнопки

Я изо всех сил пытаюсь заставить эту кнопку выглядеть красиво, когда родитель заставляет ее растягиваться. Например, поместить эту кнопку в столбец с CrossAxisAlignment.stretch . Я бы хотел, чтобы значок и текст оставались такими, какие они есть, а свободное пространство «добавлялось» к синему с правой стороны.

Как вы можете видеть из кода, это RaisedButton с Icon и Text , плюс некоторое заполнение (как определено стандартами Google). Он использует Row с 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"),
            ),
          ],
        ),
      ),
    );
  

Я попытался добавить Spacer в строку в качестве последнего виджета, но это приводит к тому, что строка всегда расширяется, чтобы заполнить своего родителя. Вместо этого я хочу, чтобы он заполнял родительский элемент только тогда, когда родитель заставляет это делать.

Есть предложения по решению этой проблемы?

Ответ №1:

Вы можете использовать Align виджет в качестве родительского элемента вашего RaisedButton , что-то вроде этого :

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

Используя это, ваш Row не будет расширяться 🙂

или

Используйте LayoutBuilder , если хотите развернуть кнопку в соответствии с родительским виджетом :

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

Комментарии:

1. Ваш первый ответ у меня не сработал. Но второй сделал 🙂