The above code is not saving state of iconData
yet.
The state of like/unlike needs to be moved up into a parent widget scope. Its value can then be referenced below in children like TextButton.
When TextButton is rebuilt (changing from unlike to like & back) it can use the state that persists above it.
Notice below how iconData
lives in the State widget. This widget designed to hold state for its children.
You can copy paste this code into a Flutter/Dart file to test:
import 'package:flutter/material.dart';
// ↓ Use this as your button
class StatefulButton extends StatefulWidget {
final double size;
final Color color;
StatefulButton({this.size = 20, this.color = Colors.black});
@override
_StatefulButtonState createState() => _StatefulButtonState();
}
class _StatefulButtonState extends State<StatefulButton> {
IconData iconData = Icons.favorite_border;
// ↑ Move your state up to here
@override
Widget build(BuildContext context) {
return Center(
child: TextButton(
child: Icon(
iconData,
size: widget.size,
color: widget.color,
),
onPressed: toggleLike,
),
);
}
void toggleLike() {
setState(() {
iconData = iconData == Icons.favorite ? Icons.favorite_border : Icons.favorite;
});
}
}
/// Just a container page for the example above
class TextButtonStatePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('TextButtonState'),
),
body: StatefulButton()
);
}
}
Here's an example of using the StatefulButton above inside a CustomScrollView. The CustomScrollView code I stole straight from the Flutter docs website. The only edit I've made is to add the StatefulButton above into each sliver, to show it changing its state when clicked.
/// Flutter code sample for CustomScrollView
import 'package:flutter/material.dart';
import 'text_button_state.dart';
/// This is the stateful widget that the main application instantiates.
class CustomScrollviewPage extends StatefulWidget {
CustomScrollviewPage({Key key}) : super(key: key);
@override
_CustomScrollviewPageState createState() => _CustomScrollviewPageState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _CustomScrollviewPageState extends State<CustomScrollviewPage> {
List<int> top = [];
List<int> bottom = [0];
@override
Widget build(BuildContext context) {
const Key centerKey = ValueKey('bottom-sliver-list');
return Scaffold(
appBar: AppBar(
title: const Text('Press on the plus to add items above and below'),
leading: IconButton(
icon: const Icon(Icons.add),
onPressed: () {
setState(() {
top.add(-top.length - 1);
bottom.add(bottom.length);
});
},
),
),
body: CustomScrollView(
center: centerKey,
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.blue[200 + top[index] % 4 * 100],
height: 100 + top[index] % 4 * 20.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Item: ${top[index]}'),
StatefulButton() // ← STATEFUL BUTTON HERE
],),
);
},
childCount: top.length,
),
),
SliverList(
key: centerKey,
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.blue[200 + bottom[index] % 4 * 100],
height: 100 + bottom[index] % 4 * 20.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Item: ${bottom[index]}'),
StatefulButton() // ← STATEFUL BUTTON HERE
],
),
);
},
childCount: bottom.length,
),
),
],
),
);
}
}