Reputation: 882
Introduction: I have been trying for some time to get the colour to toggle when I press a chip to no success. It would be a great service to me if someone could tell me what I am doing wrong in my code.
Expectation: I want the toggle method to switch the 'isSelected' boolean. value when a chip is pressed. Absolutely nothing happens when I press the buttons. I see that value does change from true to false, but it doesn't change my colour as expected and it won't change the value again after the first press.
Code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.deepPurple,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
List<Actions> actions = Actions.all();
List<Widget> newWidgets = [];
for (var i in actions) {
newWidgets.add(myChips(
isSelected: i.isSelected,
chipName: i.name,
function: () {
setState(() {
i.toggle();
print(i.isSelected);
});
}));
}
return Scaffold(
appBar: AppBar(
title: Text('Them'),
),
body: Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Text('Test'),
pinned: true,
expandedHeight: 400.0,
flexibleSpace: FlexibleSpaceBar(
background: Image.asset('assets/abc.png'),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => Container(
child: Column(
children: <Widget>[
Column(
children: <Widget>[
Container(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'Name of Chips',
style: TextStyle(
color: Colors.black,
fontSize: 24.0,
fontWeight: FontWeight.bold,
),
),
),
),
Wrap(
direction: Axis.horizontal,
spacing: 10.0,
runSpacing: 5.0,
children: newWidgets,
),
categoryDivider(context),
],
)
],
),
),
childCount: 1,
),
),
],
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
Container myChips({bool isSelected, String chipName, Function function}) {
return Container(
child: RaisedButton(
color: isSelected ? Color(0xffeadffd) : Color(0xffededed),
child: Text(
chipName,
style: TextStyle(
color: new Color(0xff6200ee),
),
),
onPressed: function,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0))),
);
}
}
// divider
Container categoryDivider(BuildContext context) {
return Container(
height: 1.0,
width: MediaQuery.of(context).size.width,
color: Colors.grey,
margin: const EdgeInsets.only(left: 10.0, right: 10.0),
);
}
class Actions {
Actions({this.name});
String name;
bool isSelected = false;
toggle() {
isSelected = !isSelected;
print(isSelected);
}
static List<Actions> all() {
return [
Actions(name: 'A'),
Actions(name: 'B'),
Actions(name: 'C'),
Actions(name: 'D'),
Actions(name: 'E'),
Actions(name: 'F'),
Actions(name: 'G'),
Actions(name: 'H'),
Actions(name: 'I'),
Actions(name: 'J'),
Actions(name: 'K'),
Actions(name: 'L'),
];
}
}
Upvotes: 1
Views: 217
Reputation: 4149
What were you doing wrong?
You were returning a new list each time you call all()
so each action was re-initialized to non-clicked, and this was happening each time you call setState()
so you were creating new actions which are not clicked every time,
solution: define the list one time only and create a getter for it
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
List<Actions> actions = Actions.all;
List<Widget> newWidgets = [];
for (var i in actions) {
newWidgets.add(myChips(
isSelected: i.isSelected,
chipName: i.name,
function: () {
setState(() {
i.toggle();
print(i.isSelected);
});
}));
}
return Scaffold(
appBar: AppBar(
title: Text('Them'),
),
body: Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Text('Test'),
pinned: true,
expandedHeight: 400.0,
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => Container(
child: Column(
children: <Widget>[
Column(
children: <Widget>[
Container(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'Name of Chips',
style: TextStyle(
color: Colors.black,
fontSize: 24.0,
fontWeight: FontWeight.bold,
),
),
),
),
Wrap(
direction: Axis.horizontal,
spacing: 10.0,
runSpacing: 5.0,
children: newWidgets,
),
categoryDivider(context),
],
)
],
),
),
childCount: 1,
),
),
],
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
Container myChips({bool isSelected, String chipName, Function function}) {
return Container(
child: RaisedButton(
color: isSelected ? Color(0xffeadffd) : Color(0xffededed),
child: Text(
chipName,
style: TextStyle(
color: new Color(0xff6200ee),
),
),
onPressed: function,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0))),
);
}
}
// divider
Container categoryDivider(BuildContext context) {
return Container(
height: 1.0,
width: MediaQuery.of(context).size.width,
color: Colors.grey,
margin: const EdgeInsets.only(left: 10.0, right: 10.0),
);
}
class Actions {
Actions({this.name});
String name;
bool isSelected = false;
toggle() {
isSelected = !isSelected;
print(isSelected);
}
static List<Actions> _all =
[
Actions(name: 'A'),
Actions(name: 'B'),
Actions(name: 'C'),
Actions(name: 'D'),
Actions(name: 'E'),
Actions(name: 'F'),
Actions(name: 'G'),
Actions(name: 'H'),
Actions(name: 'I'),
Actions(name: 'J'),
Actions(name: 'K'),
Actions(name: 'L'),
];
static get all => _all;
}
Upvotes: 1