Reputation: 2383
I am not sure I have built my code properly, but I was trying to save time on my first app project.
I have a page where I will be generating several selection buttons that I want text added to a list when you push this button. I chose not to build a traditional button but instead it goes to another widget that I can control the state with.
The problem i am having, is this selector button seems to be working fine. It changes and to verify it is being added to the list, I have it printing to the console and can see it.
The problem is my display container is not updating when I select the button.
I have tried a global key, but the problem is that since the buttons are getting generated, they share a global key. 1 button seems to be fine, I can pass the key along, but I am also limited in my knowledge of all this, so I could be doing something wrong.
My current path to the code is the following. Main Page -> Categories -> Sub Categories -> Page(digital in this case) -> Tags(the buttons).
import 'package:flutter/material.dart';
import 'package:onlytagsprod/widgets/tag.dart';
final digital = new GlobalKey<DigitalState>();
class Digital extends StatefulWidget {
Digital({ Key key }) : super(key: key);
@override
DigitalState createState() => DigitalState();
}
class DigitalState extends State<Digital> {
final postRefresh = ChangeNotifier();
bool digitalSelected = false;
List digitalHash = new List();
String displays;
@override
void initState() {
super.initState();
}
callback() {
setState(() {
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xff0E0E0F),
appBar: AppBar(
iconTheme: IconThemeData(
color: Color(0xffff9900),
),
centerTitle: true,
backgroundColor: Colors.black,
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
"#",
style: TextStyle(
fontSize: 25,
color: Color(0xffff9900),
fontFamily: 'Dokyo'),
),
Text(
"digital",
style: TextStyle(color: Colors.white, fontFamily: 'Dokyo'),
)
],
),
),
body: Column(children: <Widget>[
Expanded(
flex: 3,
child: Container(
child: Row(
children: <Widget>[
//Display the List here*********************************************
for (var digitalHashs in digitalHash)
Text(
digitalHashs,
style: TextStyle(color: Colors.white, fontSize: 20))
],
),
color: Colors.blue),
),
Expanded(
flex: 6,
child: Container(
color: Colors.black,
child: ListView(
padding: EdgeInsets.fromLTRB(25, 5, 25, 5),
children: <Widget>[
Tag(
tag: "#Digital",
isSelected: digitalSelected,
list: digitalHash,
),
Tag(
tag: "#DigitalLife",
isSelected: digitalSelected,
list: digitalHash,
),
],
),
),
)
]));
}
}
This display page i want to be able to add as many Tag options as I want.
This is the Tag Page.
import 'package:flutter/material.dart';
import 'package:onlytagsprod/subpages/digital.dart';
class Tag extends StatefulWidget {
final String tag;
bool isSelected;
List list;
Function(List) callback;
Tag(
{Key key,
@required this.tag,
@required this.isSelected,
this.list,
this.callback})
: super(key: key);
@override
_TagState createState() => _TagState();
}
class _TagState extends State<Tag> with SingleTickerProviderStateMixin {
AnimationController _animationController;
@override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 300));
}
@override
void dispose() {
super.dispose();
_animationController.dispose();
}
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.fromLTRB(0, 5, 0, 5),
height: 50,
decoration: BoxDecoration(
color: widget.isSelected ? Color(0xffff9900) : Colors.black,
border: Border.all(color: Colors.white),
borderRadius: BorderRadius.circular(10)),
child: InkWell(
onTap: () {
_handleOnPressed();
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(20, 0, 0, 0),
alignment: Alignment.centerLeft,
child: Text(
widget.tag,
style: TextStyle(
fontSize: 20,
color: widget.isSelected ? Colors.black : Colors.white,
fontFamily: 'Dokyo'),
)),
Container(
padding: EdgeInsets.fromLTRB(0, 0, 20, 0),
child: AnimatedIcon(
icon: AnimatedIcons.home_menu,
progress: _animationController,
color: widget.isSelected ? Colors.black : Colors.white,
))
],
),
),
);
}
void _handleOnPressed() {
setState(() {
widget.isSelected = !widget.isSelected;
widget.isSelected
? _animationController.forward()
: _animationController.reverse();
widget.isSelected ? widget.list.add(widget.tag) : widget.list.remove(widget.tag);
print(widget.list);
});
}
}
The code has gotten a bit sloppy since I have tried every way I know how to address the state change... so I am aware of the unneeded stuff.
I am just at my newbie wits end
Upvotes: 0
Views: 2143
Reputation: 24781
The easiest way to get state changes to a parent or ancestor is via a callback method. That being said, you already define a callback
field in the Tag
class, but neither the build method in the parent widget nor the _TagState
class is referencing it at all.
All you should need to do is change the _handleOnPressed
method to execute the callback:
void _handleOnPressed() {
...
widget.callback?.call(widget.list);
}
and change the constructors for Tag
in the parent widget to assign them:
Tag(
tag: "#DigitalLife",
isSelected: digitalSelected,
list: digitalHash,
callback: (list) => setState(() => digitalHash = list),
),
Upvotes: 2