我的屏幕中有一个带有 ListTile 的 ListView,我在 MaterialApp 中定义了两个主题,并根据 themeBloc 的状态更改 themeMode,如下所示。
MaterialApp(
theme: AppTheme.light,
darkTheme: AppTheme.dark,
themeMode: context.watch<ThemeBloc>().state,
),
但是当我切换主题时,列表图块尾随文本小部件中的颜色没有改变。
ListTile(
leadingAndTrailingTextStyle : Theme.of(context).textTheme.labelMedium,
title: Text(state.data.elementAt(index).stockName),
trailing: Text("My text which should change color based on theme"),
),
labelMedium 有浅色和深色主题两种不同的颜色
static ThemeData light = ThemeData(
useMaterial3: true,
colorScheme: lightColorScheme,
brightness: Brightness.light,
fontFamily: GoogleFonts.montserrat().fontFamily,
textTheme: TextTheme(
labelMedium: TextStyle(
color: lightColorScheme.onPrimaryContainer,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
);
static ThemeData dark = ThemeData(
useMaterial3: true,
colorScheme: darkColorScheme,
brightness: Brightness.dark,
fontFamily: GoogleFonts.montserrat().fontFamily,
textTheme: TextTheme(
labelMedium: TextStyle(
color: darkColorScheme.onPrimaryContainer,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
);
我在应用程序栏中有一个开关,可以将主题从浅色切换到深色,这会在 ThemeBloc 中添加一个事件。 如果我不向尾随小部件提供任何 textStyle,列表图块的颜色会从黑色变为白色,但是当我提供我的样式时,它不起作用。
还有一件事,如果我切换到深色主题,颜色不会改变,但是当我转到另一个屏幕并返回到此屏幕时,颜色会改变。
我尝试为文本小部件提供相同的样式,但它也不起作用。
编辑:检查此示例https://zapp.run/edit/flutter-zr3806pdr390?entry=lib/main.dart&file=lib/main.dart
第二个屏幕无法工作,但第三个屏幕可以工作。
我遇到了同样的问题,所以我尝试了两种方法,但不确定哪一种有效。
我不知道你用来更改主题的逻辑,但我是这样做的:
class AppWidget extends StatelessWidget {
AppWidget({super.key});
final themeProvider = ThemeProvider.getInstance();
@override
Widget build(BuildContext context) {
final appRouter = router();
//themeProvider.loadTheme();
return ListenableBuilder(
builder: (context, child) {
return MaterialApp.router(
title: 'Chess versus',
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
localeResolutionCallback: (locale, supportedLocales) {
if (locale == null) return const Locale('en');
for (var supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale.languageCode) {
return supportedLocale;
}
}
return const Locale('en');
},
theme: lightTheme,
darkTheme: darkTheme,
themeMode: themeProvider.themeMode,
routerConfig: appRouter,
);
},
listenable: themeProvider,
);
}
}
我的主题切换状态管理器类:
忽略变量 themeService
class ThemeProvider extends ChangeNotifier {
final themeService = ThemeService();
static ThemeProvider? _instance;
ThemeProvider._();
ThemeState state = LightThemeState();
ThemeMode get themeMode => state.themeMode;
switchTheme() {
if (state is LightThemeState) {
state = DarkThemeState();
} else if (state is DarkThemeState) {
state = LightThemeState();
}
themeService.saveLocalTheme(state.themeMode);
notifyListeners();
}
}
sealed class ThemeState {
late final ThemeMode themeMode;
}
class LightThemeState extends ThemeState {
@override
final ThemeMode themeMode = ThemeMode.light;
}
class DarkThemeState extends ThemeState {
@override
final ThemeMode themeMode = ThemeMode.dark;
}
1 - 我正在使用 ListView.builder 并将其切换为常规 ListView。它们有一个区别,涉及显示和构建包含许多项目的列表,这可能与此颜色变化错误有关。就我而言,当我滚动页面查看隐藏的 ListTile 项目时,它们没有出现错误。此外,滚动期间消失的错误已修复,并在重新出现时显示正确的颜色。
ListView(
children: state.tournaments.map((tournament) {
return Align(
alignment: Alignment.center,
child: Container(
margin: EdgeInsets.symmetric(
vertical: 8,
horizontal: Dimens.of(context)
.paddingScreenHorizontal),
child: ListTile(
horizontalTitleGap: Dimens.of(context)
.paddingScreenHorizontal,
minVerticalPadding: Dimens.of(context)
.paddingScreenVertical,
tileColor: Theme.of(context)
.colorScheme
.secondary,
title: Text(
tournament.getName,
style: Theme.of(context)
.textTheme
.titleMedium,
),
subtitle: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
tournament.getDescription ??
AppLocalizations.of(context)!
.tournamentNullDescription,
),
Text(
tournament.getTypeName.toString(),
),
Text(
DateFormat('dd/MM/yyyy').format(
tournament.getStartedAt),
)
])),
),
);
}).toList(),
),
2 - 我在配置主题的文件中设置了 ListTile 的默认主题。这样,我就不需要用属性来扰乱小部件,从而保持代码简洁。这里很乱,但在项目中,它被分成单独的文件(笑)。
ThemeData get lightTheme => ThemeHelper().lightThemeData;
ThemeData get darkTheme => ThemeHelper().darkThemeData;
class ThemeHelper {
final Map<String, ColorScheme> _supportedColors = {
'light': AppColors.lightCodeScheme,
'dark': AppColors.darkCodeScheme,
};
ThemeData get lightThemeData => _getTheme('light');
ThemeData get darkThemeData => _getTheme('dark');
ThemeData _getTheme(String theme) {
ColorScheme colorScheme =
_supportedColors[theme] ?? AppColors.lightCodeScheme;
return ThemeData(
iconTheme: iconTheme(colorScheme),
dialogTheme: dialogTheme(colorScheme),
colorScheme: _supportedColors[theme],
textTheme: TextThemes.textTheme(colorScheme),
appBarTheme: appBarTheme(colorScheme),
listTileTheme: listTileTheme(colorScheme),
switchTheme: switchTheme(colorScheme),
inputDecorationTheme: inputDecorationTheme(colorScheme),
);
}
}
class AppColors {
static const Color darkBlueGray = Color(0xFF2C3E50);
static const Color blueGray = Color(0xFF375A7F);
static const Color drakGray = Color(0xFF222222);
static const Color gray = Color(0xFF3A3A3A);
static const Color lightGray200 = Color(0xFF75818C);
static const Color lightGray100 = Color(0xFF7F8C8D);
static const Color lightGray = Color(0xFFB9C4C4);
static const Color lightBlue = Color(0XFFD7E3FF);
static const Color blue = Color(0XFF055AB2);
static const Color white = Color(0XFFFFFFFF);
static const Color red = Color(0XFFBA1A1A);
static const Color purple = Color(0XFF810081);
static const Color pink = Color(0XFFFDAFF2);
static const Color lightRedPink = Color(0XFFFFB4AB);
static const Color redOrange = Color(0XFFC44133);
static const Color lightPurple = Color(0XFFEBDCFF);
// Esquema de cores claro
static const lightCodeScheme = ColorScheme.light(
brightness: Brightness.light,
primary: darkBlueGray,
onPrimary: white,
//surface: lightGray,
secondary: lightGray,
error: white,
onError: red,
);
// Esquema de cores escuro
static const darkCodeScheme = ColorScheme.dark(
brightness: Brightness.dark,
surface: drakGray,
primary: blueGray,
onPrimary: white,
secondary: gray,
error: redOrange,
onError: white,
);
}
ListTileThemeData listTileTheme(ColorScheme colorScheme) => ListTileThemeData(
tileColor: colorScheme.secondary,
textColor: colorScheme.onPrimary,
iconColor: colorScheme.onPrimary,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
);