mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Expose the duration and curve for theme animation in MaterialApp. (#107383)
This commit is contained in:
parent
ed65b7e2c1
commit
50cde354c4
@ -220,6 +220,8 @@ class MaterialApp extends StatefulWidget {
|
||||
this.highContrastTheme,
|
||||
this.highContrastDarkTheme,
|
||||
this.themeMode = ThemeMode.system,
|
||||
this.themeAnimationDuration = kThemeAnimationDuration,
|
||||
this.themeAnimationCurve = Curves.linear,
|
||||
this.locale,
|
||||
this.localizationsDelegates,
|
||||
this.localeListResolutionCallback,
|
||||
@ -271,6 +273,8 @@ class MaterialApp extends StatefulWidget {
|
||||
this.highContrastTheme,
|
||||
this.highContrastDarkTheme,
|
||||
this.themeMode = ThemeMode.system,
|
||||
this.themeAnimationDuration = kThemeAnimationDuration,
|
||||
this.themeAnimationCurve = Curves.linear,
|
||||
this.locale,
|
||||
this.localizationsDelegates,
|
||||
this.localeListResolutionCallback,
|
||||
@ -472,6 +476,30 @@ class MaterialApp extends StatefulWidget {
|
||||
/// system what kind of theme is being used.
|
||||
final ThemeMode? themeMode;
|
||||
|
||||
/// The duration of animated theme changes.
|
||||
///
|
||||
/// When the theme changes (either by the [theme], [darkTheme] or [themeMode]
|
||||
/// parameters changing) it is animated to the new theme over time.
|
||||
/// The [themeAnimationDuration] determines how long this animation takes.
|
||||
///
|
||||
/// To have the theme change immediately, you can set this to [Duration.zero].
|
||||
///
|
||||
/// The default is [kThemeAnimationDuration].
|
||||
///
|
||||
/// See also:
|
||||
/// [themeAnimationCurve], which defines the curve used for the animation.
|
||||
final Duration themeAnimationDuration;
|
||||
|
||||
/// The curve to apply when animating theme changes.
|
||||
///
|
||||
/// The default is [Curves.linear].
|
||||
///
|
||||
/// This is ignored if [themeAnimationDuration] is [Duration.zero].
|
||||
///
|
||||
/// See also:
|
||||
/// [themeAnimationDuration], which defines how long the animation is.
|
||||
final Curve themeAnimationCurve;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.color}
|
||||
final Color? color;
|
||||
|
||||
@ -896,6 +924,8 @@ class _MaterialAppState extends State<MaterialApp> {
|
||||
cursorColor: effectiveCursorColor,
|
||||
child: AnimatedTheme(
|
||||
data: theme,
|
||||
duration: widget.themeAnimationDuration,
|
||||
curve: widget.themeAnimationCurve,
|
||||
child: widget.builder != null
|
||||
? Builder(
|
||||
builder: (BuildContext context) {
|
||||
|
@ -853,6 +853,88 @@ void main() {
|
||||
tester.binding.platformDispatcher.clearPlatformBrightnessTestValue();
|
||||
});
|
||||
|
||||
testWidgets('MaterialApp animates theme changes', (WidgetTester tester) async {
|
||||
final ThemeData lightTheme = ThemeData.light();
|
||||
final ThemeData darkTheme = ThemeData.dark();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: lightTheme,
|
||||
darkTheme: darkTheme,
|
||||
themeMode: ThemeMode.light,
|
||||
home: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return const Scaffold();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(tester.widget<Material>(find.byType(Material)).color, lightTheme.scaffoldBackgroundColor);
|
||||
|
||||
// Change to dark theme
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.light(),
|
||||
darkTheme: ThemeData.dark(),
|
||||
themeMode: ThemeMode.dark,
|
||||
home: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return const Scaffold();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Wait half kThemeAnimationDuration = 200ms.
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
|
||||
// Default curve is linear so background should be half way between
|
||||
// the two colors.
|
||||
final Color halfBGColor = Color.lerp(lightTheme.scaffoldBackgroundColor, darkTheme.scaffoldBackgroundColor, 0.5)!;
|
||||
expect(tester.widget<Material>(find.byType(Material)).color, halfBGColor);
|
||||
});
|
||||
|
||||
testWidgets('MaterialApp theme animation can be turned off', (WidgetTester tester) async {
|
||||
final ThemeData lightTheme = ThemeData.light();
|
||||
final ThemeData darkTheme = ThemeData.dark();
|
||||
int scaffoldRebuilds = 0;
|
||||
|
||||
final Widget scaffold = Builder(
|
||||
builder: (BuildContext context) {
|
||||
scaffoldRebuilds++;
|
||||
// Use Theme.of() to ensure we are building when the theme changes.
|
||||
return Scaffold(backgroundColor: Theme.of(context).scaffoldBackgroundColor);
|
||||
},
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: lightTheme,
|
||||
darkTheme: darkTheme,
|
||||
themeMode: ThemeMode.light,
|
||||
themeAnimationDuration: Duration.zero,
|
||||
home: scaffold,
|
||||
),
|
||||
);
|
||||
expect(tester.widget<Material>(find.byType(Material)).color, lightTheme.scaffoldBackgroundColor);
|
||||
expect(scaffoldRebuilds, 1);
|
||||
|
||||
// Change to dark theme
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.light(),
|
||||
darkTheme: ThemeData.dark(),
|
||||
themeMode: ThemeMode.dark,
|
||||
themeAnimationDuration: Duration.zero,
|
||||
home: scaffold,
|
||||
),
|
||||
);
|
||||
|
||||
// Wait for any animation to finish.
|
||||
await tester.pumpAndSettle();
|
||||
expect(tester.widget<Material>(find.byType(Material)).color, darkTheme.scaffoldBackgroundColor);
|
||||
expect(scaffoldRebuilds, 2);
|
||||
});
|
||||
|
||||
testWidgets('MaterialApp switches themes when the Window platformBrightness changes.', (WidgetTester tester) async {
|
||||
// Mock the Window to explicitly report a light platformBrightness.
|
||||
final TestWidgetsFlutterBinding binding = tester.binding;
|
||||
|
Loading…
Reference in New Issue
Block a user