У меня есть список поднятых кнопок, я хочу, чтобы цвет фона выбранной кнопки изменился в ее 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 изменяется, но фон соответственно не меняется
Вы можете использовать это решение: stackoverflow.com/a/61526932/865249
Если я не ошибаюсь, то, что вы пытаетесь сделать, уже обрабатывается флаттером. Я думаю, все, что вам нужно сделать, это установить 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
.
Вот очень простой подход.
bool isButtonPressed = false;
RaisedButton(
color: isButtonPressed ? Colors.green : Colors.red,
onPressed: () {
setState(() {
isButtonPressed =!isButtonPressed;
});
},
),
Спасибо за быстрый ответ.. к сожалению, он все еще работает.. Я думаю, проблема в том, что мои виджеты находятся внутри списка..