Как динамически изменить цвет фона поднятой кнопки в onPressed ()

У меня есть список поднятых кнопок, я хочу, чтобы цвет фона выбранной кнопки изменился в ее onPressed ()

Я попытался изменить цвет в setState, но ничего не сделал.

Это функция, которая генерирует список кнопок

List<Widget> _makeZoneList(List<Zone> zones) {
    List<Widget>Buttons = new List();
    for (int i = 0; i < zones.length; i++) {
      Buttons.add(RaisedButton(
        color: zones[i].isSelected ? AppColors.primaryColor : AppColors.white,
        onPressed: () {
          setState(() {
            if (zones[i].isSelected){
              zones[i].isSelected = false;
            }
            else{
              zones[i].isSelected = true;
            }
            print(zones[i].isSelected.toString());
          });
        },
        child: Text(zones.elementAt(i).text)
      ));
    }
    return Buttons;
  }

Здесь я вызываю функцию

Widget _zoneBody() {
    return Padding(
        padding: EdgeInsets.all(32),
        child: StreamBuilder<List<Zone>>(
            stream: GetterBloc.zonesStream,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return new Container();
              } else {
                if (snapshot.hasData) {
                     return Wrap(
                          spacing: 6.0, // gap between adjacent chips
                          children: _makeZoneList(snapshot.data));

                } else {
                  return new Container();
                }
              }
            }));
  }

Когда я нажимаю любую кнопку, ее значение isSelected изменяется, но фон не меняется соответственно.


person Ghada Shebl    schedule 10.04.2019    source источник
comment
Спасибо за быстрый ответ .. к сожалению, сейчас он все еще работает .. Я думаю, проблема в том, что у меня есть виджеты внутри списка ..   -  person Ghada Shebl    schedule 11.04.2019
comment
Вы можете использовать это решение: stackoverflow.com/a/61526932/865249   -  person Ricardo    schedule 30.04.2020


Ответы (4)


Обновленный ответ (ElevatedButton)

Поскольку RaisedButton устарел, используйте ElevatedButton:

введите описание изображения здесь

Код:

class _MyState extends State<MyPage> {
  bool _flag = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => setState(() => _flag = !_flag),
          child: Text(_flag ? 'Red' : 'Green'),
          style: ElevatedButton.styleFrom(
            primary: _flag ? Colors.red : Colors.teal, // This is what you need!
          ),
        ),
      ),
    );
  }
}

Старый ответ

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

List<bool> _list = [true, false, true, false];

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text("Title")),
    body: ListView(children: _buildButtons()),
  );
}

List<Widget> _buildButtons() {
  List<Widget> listButtons = List.generate(_list.length, (i) {
    return RaisedButton(
      color: _list[i] ? Colors.green : Colors.red,
      onPressed: () {
        setState(() {
          _list[i] = !_list[i];
        });
      },
      child: Text("Button #${i}"),
    );
  });
  return listButtons;
}

Выход:

введите описание изображения здесь

person CopsOnRoad    schedule 11.04.2019
comment
Не забудьте установить свойство onPressed. - person Adam Smaka; 16.02.2021

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

Однако есть также причина, по которой то, что вы делаете, не работает. Вы не включили достаточно кода, чтобы я мог сказать, но я считаю, что причина, по которой то, что вы делаете, не работает, заключается в том, что у вас есть список данных, которые вы изменяете при нажатии кнопки (т.е. zones[i].isSelected = false;) . Вы делаете это в setState, но способ, которым flutter проверяет, нуждается ли что-то в перестройке, заключается в выполнении сравнения на равенство для членов State (т.е. он проверяет, являются ли зоны == зоны).

Поскольку «зоны» - это просто список, который фактически является одним и тем же списком для старого и нового состояний, flutter будет предполагать, что ничего не изменилось, и не будет беспокоиться о восстановлении.

Есть два простых способа обойти это. Можно было бы делать копию списка каждый раз, когда он изменяется, и устанавливать для этого член zones, чтобы при флаттере выполнялось сравнение old.zones != new.zones. Другой способ - сохранить отдельный объект, который вы изменяете каждый раз при изменении списка (я обычно использую целое число с именем changeCounter, которое я увеличиваю каждый раз при изменении списка), чтобы вы могли «обмануть» флаттер и перестроить его.

person rmtmckenzie    schedule 10.04.2019

Вот очень простой подход.

bool isButtonPressed = false;

RaisedButton(
            color: isButtonPressed ? Colors.green : Colors.red,
            onPressed: () {
              setState(() {
                isButtonPressed =!isButtonPressed;
              });
            },
          ),
person Nikhil Singh    schedule 13.02.2020

Что вы можете сделать, так это создать свойство «цвет» (не обязательно устанавливать для него какое-либо значение) в классе Zone. Затем установите для свойства color RaisedButton значение zone.color ??= AppColors.primaryColor.

А теперь внутри функции onPressed вы можете проверить, не установлен ли !zone.isSelected, а затем zone.color = Colors.white.

Ниже представлена ​​реализация создания RaisedButton. Вы также можете проверить полную реализацию здесь

List<Widget> _createButton(BuildContext context, List<Zone> zones) {
    return zones.map((Zone zone) {
      return RaisedButton(
        onPressed: () {
          setState(() {
            if (!zone.isSelected) {
              zone.color = AppColors.white;
            }
          });
        },
        color: zone.color ??= Theme.of(context).primaryColor,
        child: Text(zone.text),
      );
    }).toList();
  }
person Ankit    schedule 11.04.2019