Recently I faced the following issue:
I have a Card inside a ListView, I wanted to theme the card by setting the color to Theme.of(context).colorScheme.surfaceContainer
but the issue now is that when I switch the theme, the color doesn't refresh.
I created a minimal reproducible example of this issue here
import 'package:flutter/material.dart';
void main() {
runApp(const MainApp());
}
class MainApp extends StatefulWidget {
const MainApp({super.key});
@override
State<MainApp> createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
ThemeMode _themeMode = ThemeMode.light;
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(),
darkTheme: ThemeData(brightness: Brightness.dark),
themeMode: _themeMode,
home: Scaffold(
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Column(
spacing: 8,
mainAxisSize: MainAxisSize.min,
children: [
ElevatedButton(
onPressed: () {
setState(() {
_themeMode = _themeMode == ThemeMode.light
? ThemeMode.dark
: ThemeMode.light;
});
},
child: Text("Change Theme")),
Expanded(child: MyList())
],
)),
),
),
);
}
}
class MyList extends StatelessWidget {
const MyList({super.key});
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return Card(
color: Theme.of(context).colorScheme.surfaceContainer,
child: ListTile(
title: Text('Item $index'),
),
);
});
}
}
As I open the app, everything looks as expected:
Now I click on the "Change Theme" button, and this happens:
Not sure if it is something I'm missing or an issue with the Flutter framework (unlikely).
I tried to remove the ListView
, and just having one Card
inside the widget fixes the issue, but of course, for my real app I need the cards to be in a ListView
.
Also note that when scrolling, if the card goes out of screen, and then scroll it back to screen, it refetches the color and displays correctly.
I thought I'll ask here before raising an issue on the Flutter GitHub repo.
Rename context
parameter inside the ListView.builder itemBuilder
to avoid conflicts with the context of the build method.
class MyList extends StatelessWidget {
const MyList({super.key});
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 10,
itemBuilder: (listViewContext, index) { // Renamed context to listViewContext
return Card(
color: Theme.of(context).colorScheme.surfaceContainer, // Uses build context
child: ListTile(
title: Text('Item $index'),
),
);
},
);
}
}