Как динамически изменить цвет фона приподнятой кнопки в 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 изменяется, но фон соответственно не меняется

Спасибо за быстрый ответ.. к сожалению, он все еще работает.. Я думаю, проблема в том, что мои виджеты находятся внутри списка..

Ghada Shebl 11.04.2019 10:57

Вы можете использовать это решение: stackoverflow.com/a/61526932/865249

Ricardo 30.04.2020 17:23
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
15
2
56 059
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

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

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

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

Что вы можете сделать, так это создать свойство «цвет» (не требуется устанавливать для него какое-либо значение) в классе 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();
  }
Ответ принят как подходящий

Обновленный ответ (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;
}

Выход:

Не забудьте установить свойство onPressed.

Adam Smaka 16.02.2021 12:07

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

bool isButtonPressed = false;

RaisedButton(
            color: isButtonPressed ? Colors.green : Colors.red,
            onPressed: () {
              setState(() {
                isButtonPressed =!isButtonPressed;
              });
            },
          ),

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