StatefulBuilder
A platonic widget that both has state and calls a closure to obtain its child widget.
The StateSetter function passed to the builder is used to invoke a rebuild instead of a typical State's State.setState.
Since the builder is re-invoked when the StateSetter is called, any variables that represents state should be kept outside the builder function.
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: const Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
const MyWidget({Key? key}) : super(key: key);
@override
State createState() => _MyWidgetState();
}
class _MyWidgetState extends State {
double lerp = 0;
Color buttonColor = Colors.blue[100]!;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
StatefulBuilder(
builder: (context, setState) {
return InexpensiveWidget(
color: Color.lerp(buttonColor, Colors.black, lerp)!,
onPressed: () => setState(() {
lerp += 0.1;
if (lerp > 1) {
lerp = 0;
}
}),
);
},
),
// Pretend `const` is not feasible here
// ignore: prefer_const_constructors
ExpensiveWidget(),
],
),
);
}
}
class InexpensiveWidget extends StatelessWidget {
const InexpensiveWidget({
Key? key,
required this.color,
required this.onPressed,
}) : super(key: key);
final VoidCallback onPressed;
final Color color;
@override
Widget build(BuildContext context) {
print(" building InexpensiveWidget");
return TextButton(
onPressed: onPressed,
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(color)),
child: const Text("I rebuild often"),
);
}
}
class ExpensiveWidget extends StatelessWidget {
const ExpensiveWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
print('Painstakingly building ExpensiveWidget');
return const Text("I'm expensive!");
}
}