Как добавить границу к кнопке флаттера?

Я совсем недавно начал трепетать, и пока мне это нравится, но я застрял на некоторых изменениях пользовательского интерфейса. Любая помощь приветствуется!

Моя цель - получить круглую кнопку со значком на синем фоне, но с более темной синей рамкой снаружи. Фотографии прилагаются.

Мой подход был:

  1. Получите круглую синюю кнопку.
  2. Поместите значок в эту кнопку.
  3. Добавьте границу.

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

Вот что у меня сейчас есть мудрый код:

  var messageBtn = new Row(
  children: <Widget>[
    new Padding(
      padding: const EdgeInsets.all(20.0),
      child: new RawMaterialButton(
        onPressed: _messages,
        child: new Padding(
          padding: const EdgeInsets.all(20.0),
          child: new Icon(
            Icons.message,
            size: 30.0,
            color: Colors.white,
          ),
        ),
        shape: new CircleBorder(),
        fillColor: Colors.deepPurple,
      ),
    ),
    new Padding(
        padding: const EdgeInsets.all(8.0),
        child: new Text(
          'Send Messages',
          style: new TextStyle(
            fontSize: 20.0,
          ),
        )),
  ],
);

Это производит это: см. снимок экрана

Я хочу это: см. второй снимок экрана

5 дизайнов темных кнопок с использованием HTML и CSS
5 дизайнов темных кнопок с использованием HTML и CSS
Здесь представлены пять дизайнов темных кнопок с кодом с использованием HTML и CSS:
13
0
24 448
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Привет Кэтлин и добро пожаловать!

Вы можете добиться того, чего хотите, углубившись в виджеты, из которых состоит MaterialButton.

Для начала вам понадобится виджет Чернила. Это предлагает более гибкий стиль с использованием КоробкаУкрашение.

Ink может затем содержать виджет Чернильница, который распознает onTap и рисует эффект всплеска. По умолчанию всплеск продолжается до краев контейнера, но вы можете сделать его круглым, присвоив InkWell действительно большой borderRadius.

Вот пример кнопки, которая вам нужна:

Material(
  type: MaterialType.transparency, //Makes it usable on any background color, thanks @IanSmith
  child: Ink(
    decoration: BoxDecoration(
      border: Border.all(color: Colors.indigoAccent, width: 4.0),
      color: Colors.indigo[900],
      shape: BoxShape.circle,
    ),
    child: InkWell(
      //This keeps the splash effect within the circle
      borderRadius: BorderRadius.circular(1000.0), //Something large to ensure a circle
      onTap: _messages,
      child: Padding(
        padding:EdgeInsets.all(20.0),
        child: Icon(
          Icons.message,
          size: 30.0,
          color: Colors.white,
        ),
      ),
    ),
  )
),

И вот результат:

screenshot of Flutter app with custom styled button

Хм, обновление сломало это? Теперь у него есть белый ящик в качестве фона из-за формы BoxDecoration. Может, этого и не заметили ..

Ian Smith 11.05.2020 08:39

@IanSmith, у меня он все еще работает на последней стабильной версии Flutter (1.17). Рад взглянуть на ваш код.

Xander 11.05.2020 10:50

@Xander вот пример приложения, показывающего проблему: pastebin.com/raw/tTCVzRmP

Ian Smith 11.05.2020 15:03

@IanSmith Спасибо, я понимаю, о чем вы. Вероятно, нам следует использовать Material(type: MaterialType.transparency). Я обновлю ответ ?

Xander 11.05.2020 17:51

Просто оберните IconButton в Container и установите его decoration следующим образом:

Container(
  decoration: BoxDecoration(
    border: Border.all(color: Colors.blue, width: 4),
    color: Colors.yellow,
    shape: BoxShape.circle,
  ),
  child: IconButton(
    iconSize: 56,
    icon: Icon(Icons.check),
    onPressed: () {},
  ),
),

Можно использовать FloatingActionButton с границей:

   FloatingActionButton(
                              mini: false,
                              backgroundColor: Colors.blue.shade900,
                              splashColor: Colors.black,
                              onPressed: () {
                                logOutDialog(context);
                              },
                              hoverElevation: 1.5,
                              shape: StadiumBorder(
                                  side: BorderSide(
                                      color: Colors.blue, width: 4)),
                              elevation: 1.5,
                              child: Icon(
                                Icons.logout,
                                color: _foregroundColor,
                              ),
                            )

Во Flutter 2 есть TextButton:

TextButton(
  style: ButtonStyle(
   side: RedSelectedBorderSide(),
  ),
  child: Text(
    "Button"
  ),
  onPressed: (){}
);

Где RedSelectedBorderSide():

class RedSelectedBorderSide extends MaterialStateBorderSide {
  @override
  BorderSide resolve(Set<MaterialState> states) {
    if (states.contains(MaterialState.selected)) {
      return BorderSide(
        width: 2,
        color: Colors.red,
      ); // 
    }
    return null;// Defer to default value on the theme or widget.
  }
}

Для TextButton

внутри style используйте side с MaterialStateProperty с BorderSide.

TextButton(
  style: ButtonStyle(
   side: MaterialStateProperty.all(
     BorderSide(width: 1, color: Colors.black),
   ),
  ),
  child: Text(
    "My Button"
  ),
  onPressed: (){}
);

Другие вопросы по теме