如果您在 AnimatedContainer 中使用依赖于亮度的颜色(例如 Theme.of(context).colorScheme.onBackground,对于深色主题为白色,对于浅色主题为黑色)并更改应用程序亮度,则 AnimatedContainer 还会根据提供的 Duration 对其颜色进行动画处理带有主题切换动画。如何从 AnimatedContainer 中禁用此附加动画?
左图是一个 AnimatedContainer,右图是一个默认容器
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
ValueNotifier<ThemeData> _theme = ValueNotifier(
ThemeData(brightness: Brightness.dark, backgroundColor: Colors.white),
);
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ValueListenableBuilder<ThemeData>(
valueListenable: _theme,
builder: (_, theme, __) => MaterialApp(
theme: theme,
title: 'Material App',
home: _Scaffold(),
),
);
}
}
class _Scaffold extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Material App Bar'),
backgroundColor: Theme.of(context).backgroundColor,
),
backgroundColor: Colors.red,
body: Center(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
AnimatedContainer(
curve: Curves.easeInOutCubic,
duration: const Duration(milliseconds: 175),
color: Theme.of(context).backgroundColor,
width: 50.0,
height: 50.0,
margin: const EdgeInsets.all(10.0),
),
Container(
color: Theme.of(context).backgroundColor,
width: 50.0,
height: 50.0,
),
],
),
ElevatedButton(
onPressed: () {
final Brightness newBrightness =
_theme.value.brightness == Brightness.dark
? Brightness.light
: Brightness.dark;
_theme.value = _theme.value.copyWith(
brightness: newBrightness,
backgroundColor: newBrightness == Brightness.dark
? Colors.white
: Colors.black,
);
},
child: const Text('switch brightness'),
),
],
),
),
);
}
}
最终,除了这个之外,我没有找到任何更好的解决方案:
您为每个动画容器提供一个密钥,如下所示:
key: !isThemeAnimationInProgress
? null // Or your own ValueKey if needed, applies once theme animation is ended
: UniqueKey(), // Applies only during theme transition
在你的主题切换回调中添加这个
/// If theme animation is currently in progress, this is set to true
bool isThemeAnimationInProgress = false;
/// Keeps track of theme animation transition.
Timer? _timer;
isThemeAnimationInProgress = true;
// In case some widget needs to know if theme switch is in progress
_timer?.cancel();
_timer = Timer(kThemeAnimationDuration, () {
isThemeAnimationInProgress = false;
});