Reverts "Introduce `AnimationStyle`" (#138628)
Reverts flutter/flutter#137945
Initiated by: HansMuller
This change reverts the following previous change:
Original Description:
This PR introduces `AnimationStyle`, it is used to override default animation curves and durations in several widgets.
fixes [Add the ability to customize MaterialApp theme animation duration](https://github.com/flutter/flutter/issues/78372)
fixes [Allow customization of showMenu transition animation curves and duration](https://github.com/flutter/flutter/issues/135638)
Here is an example where popup menu curve and transition duration is overriden:
```dart
popUpAnimationStyle: AnimationStyle(
curve: Easing.emphasizedAccelerate,
duration: Durations.medium4,
),
```
Set `AnimationStyle.noAnimation` to disable animation.
```dart
return MaterialApp(
themeAnimationStyle: AnimationStyle.noAnimation,
```
diff --git a/examples/api/lib/material/app/app.0.dart b/examples/api/lib/material/app/app.0.dart
deleted file mode 100644
index 5df0bde..0000000
--- a/examples/api/lib/material/app/app.0.dart
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2014 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:flutter/material.dart';
-
-/// Flutter code sample for [MaterialApp].
-
-void main() {
- runApp(const MaterialAppExample());
-}
-
-enum AnimationStyles { defaultStyle, custom, none }
-const List<(AnimationStyles, String)> animationStyleSegments = <(AnimationStyles, String)>[
- (AnimationStyles.defaultStyle, 'Default'),
- (AnimationStyles.custom, 'Custom'),
- (AnimationStyles.none, 'None'),
-];
-
-class MaterialAppExample extends StatefulWidget {
- const MaterialAppExample({super.key});
-
- @override
- State<MaterialAppExample> createState() => _MaterialAppExampleState();
-}
-
-class _MaterialAppExampleState extends State<MaterialAppExample> {
- Set<AnimationStyles> _animationStyleSelection = <AnimationStyles>{AnimationStyles.defaultStyle};
- AnimationStyle? _animationStyle;
- bool isDarkTheme = false;
-
- @override
- Widget build(BuildContext context) {
- return MaterialApp(
- themeAnimationStyle: _animationStyle,
- themeMode: isDarkTheme ? ThemeMode.dark : ThemeMode.light,
- theme: ThemeData(colorSchemeSeed: Colors.green),
- darkTheme: ThemeData(
- colorSchemeSeed: Colors.green,
- brightness: Brightness.dark,
- ),
- home: Scaffold(
- body: Center(
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- SegmentedButton<AnimationStyles>(
- selected: _animationStyleSelection,
- onSelectionChanged: (Set<AnimationStyles> styles) {
- setState(() {
- _animationStyleSelection = styles;
- switch (styles.first) {
- case AnimationStyles.defaultStyle:
- _animationStyle = null;
- case AnimationStyles.custom:
- _animationStyle = AnimationStyle(
- curve: Easing.emphasizedAccelerate,
- duration: const Duration(seconds: 1),
- );
- case AnimationStyles.none:
- _animationStyle = AnimationStyle.noAnimation;
- }
- });
- },
- segments: animationStyleSegments
- .map<ButtonSegment<AnimationStyles>>(((AnimationStyles, String) shirt) {
- return ButtonSegment<AnimationStyles>(value: shirt.$1, label: Text(shirt.$2));
- })
- .toList(),
- ),
- const SizedBox(height: 10),
- OutlinedButton.icon(
- onPressed: () {
- setState(() {
- isDarkTheme = !isDarkTheme;
- });
- },
- icon: Icon(isDarkTheme ? Icons.wb_sunny : Icons.nightlight_round),
- label: const Text('Switch Theme Mode'),
- ),
- ],
- ),
- ),
- ),
- );
- }
-}
diff --git a/examples/api/lib/material/popup_menu/popup_menu.0.dart b/examples/api/lib/material/popup_menu/popup_menu.0.dart
index cfdc80a..47f7c82 100644
--- a/examples/api/lib/material/popup_menu/popup_menu.0.dart
+++ b/examples/api/lib/material/popup_menu/popup_menu.0.dart
@@ -30,7 +30,7 @@
}
class _PopupMenuExampleState extends State<PopupMenuExample> {
- SampleItem? selectedItem;
+ SampleItem? selectedMenu;
@override
Widget build(BuildContext context) {
@@ -38,10 +38,11 @@
appBar: AppBar(title: const Text('PopupMenuButton')),
body: Center(
child: PopupMenuButton<SampleItem>(
- initialValue: selectedItem,
+ initialValue: selectedMenu,
+ // Callback that sets the selected popup menu item.
onSelected: (SampleItem item) {
setState(() {
- selectedItem = item;
+ selectedMenu = item;
});
},
itemBuilder: (BuildContext context) => <PopupMenuEntry<SampleItem>>[
diff --git a/examples/api/lib/material/popup_menu/popup_menu.1.dart b/examples/api/lib/material/popup_menu/popup_menu.1.dart
index a961d40..2a3a4d6 100644
--- a/examples/api/lib/material/popup_menu/popup_menu.1.dart
+++ b/examples/api/lib/material/popup_menu/popup_menu.1.dart
@@ -31,7 +31,7 @@
}
class _PopupMenuExampleState extends State<PopupMenuExample> {
- SampleItem? selectedItem;
+ SampleItem? selectedMenu;
@override
Widget build(BuildContext context) {
@@ -39,10 +39,11 @@
appBar: AppBar(title: const Text('PopupMenuButton')),
body: Center(
child: PopupMenuButton<SampleItem>(
- initialValue: selectedItem,
+ initialValue: selectedMenu,
+ // Callback that sets the selected popup menu item.
onSelected: (SampleItem item) {
setState(() {
- selectedItem = item;
+ selectedMenu = item;
});
},
itemBuilder: (BuildContext context) => <PopupMenuEntry<SampleItem>>[
diff --git a/examples/api/lib/material/popup_menu/popup_menu.2.dart b/examples/api/lib/material/popup_menu/popup_menu.2.dart
deleted file mode 100644
index 50947b1..0000000
--- a/examples/api/lib/material/popup_menu/popup_menu.2.dart
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2014 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:flutter/material.dart';
-
-/// Flutter code sample for [PopupMenuButton].
-
-void main() => runApp(const PopupMenuApp());
-
-class PopupMenuApp extends StatelessWidget {
- const PopupMenuApp({super.key});
-
- @override
- Widget build(BuildContext context) {
- return const MaterialApp(
- home: PopupMenuExample(),
- );
- }
-}
-
-enum AnimationStyles { defaultStyle, custom, none }
-const List<(AnimationStyles, String)> animationStyleSegments = <(AnimationStyles, String)>[
- (AnimationStyles.defaultStyle, 'Default'),
- (AnimationStyles.custom, 'Custom'),
- (AnimationStyles.none, 'None'),
-];
-
-enum Menu { preview, share, getLink, remove, download }
-
-class PopupMenuExample extends StatefulWidget {
- const PopupMenuExample({super.key});
-
- @override
- State<PopupMenuExample> createState() => _PopupMenuExampleState();
-}
-
-class _PopupMenuExampleState extends State<PopupMenuExample> {
- Set<AnimationStyles> _animationStyleSelection = <AnimationStyles>{AnimationStyles.defaultStyle};
- AnimationStyle? _animationStyle;
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- body: SafeArea(
- child: Padding(
- padding: const EdgeInsets.only(top: 50),
- child: Align(
- alignment: Alignment.topCenter,
- child: Column(
- mainAxisSize: MainAxisSize.min,
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- SegmentedButton<AnimationStyles>(
- selected: _animationStyleSelection,
- onSelectionChanged: (Set<AnimationStyles> styles) {
- setState(() {
- _animationStyleSelection = styles;
- switch (styles.first) {
- case AnimationStyles.defaultStyle:
- _animationStyle = null;
- case AnimationStyles.custom:
- _animationStyle = AnimationStyle(
- curve: Easing.emphasizedDecelerate,
- duration: const Duration(seconds: 3),
- );
- case AnimationStyles.none:
- _animationStyle = AnimationStyle.noAnimation;
- }
- });
- },
- segments: animationStyleSegments
- .map<ButtonSegment<AnimationStyles>>(((AnimationStyles, String) shirt) {
- return ButtonSegment<AnimationStyles>(value: shirt.$1, label: Text(shirt.$2));
- })
- .toList(),
- ),
- const SizedBox(height: 10),
- PopupMenuButton<Menu>(
- popUpAnimationStyle: _animationStyle,
- icon: const Icon(Icons.more_vert),
- onSelected: (Menu item) { },
- itemBuilder: (BuildContext context) => <PopupMenuEntry<Menu>>[
- const PopupMenuItem<Menu>(
- value: Menu.preview,
- child: ListTile(
- leading: Icon(Icons.visibility_outlined),
- title: Text('Preview'),
- ),
- ),
- const PopupMenuItem<Menu>(
- value: Menu.share,
- child: ListTile(
- leading: Icon(Icons.share_outlined),
- title: Text('Share'),
- ),
- ),
- const PopupMenuItem<Menu>(
- value: Menu.getLink,
- child: ListTile(
- leading: Icon(Icons.link_outlined),
- title: Text('Get link'),
- ),
- ),
- const PopupMenuDivider(),
- const PopupMenuItem<Menu>(
- value: Menu.remove,
- child: ListTile(
- leading: Icon(Icons.delete_outline),
- title: Text('Remove'),
- ),
- ),
- const PopupMenuItem<Menu>(
- value: Menu.download,
- child: ListTile(
- leading: Icon(Icons.download_outlined),
- title: Text('Download'),
- ),
- ),
- ],
- ),
- ],
- ),
- ),
- ),
- ),
- );
- }
-}
diff --git a/examples/api/test/material/app/app.0_test.dart b/examples/api/test/material/app/app.0_test.dart
deleted file mode 100644
index 7e17e9e..0000000
--- a/examples/api/test/material/app/app.0_test.dart
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:flutter/material.dart';
-import 'package:flutter_api_samples/material/app/app.0.dart'
- as example;
-import 'package:flutter_test/flutter_test.dart';
-
-void main() {
- testWidgets('Theme Animation can be customized using AnimationStyle', (WidgetTester tester) async {
- await tester.pumpWidget(
- const example.MaterialAppExample(),
- );
-
- Material getScaffoldMaterial() {
- return tester.widget<Material>(find.descendant(
- of: find.byType(Scaffold),
- matching: find.byType(Material).first,
- ));
- }
-
- final ThemeData lightTheme = ThemeData(colorSchemeSeed: Colors.green);
- final ThemeData darkTheme = ThemeData(
- colorSchemeSeed: Colors.green,
- brightness: Brightness.dark,
- );
-
- // Test the default animation.
- expect(getScaffoldMaterial().color, lightTheme.colorScheme.background);
-
- await tester.tap(find.text( 'Switch Theme Mode'));
- await tester.pump();
- // Advance the animation by half of the default duration.
- await tester.pump(const Duration(milliseconds: 100));
-
- // The Scaffold background color is updated.
- expect(
- getScaffoldMaterial().color,
- Color.lerp(lightTheme.colorScheme.background, darkTheme.colorScheme.background, 0.5),
- );
-
- await tester.pumpAndSettle();
-
- // The Scaffold background color is now fully dark.
- expect(getScaffoldMaterial().color, darkTheme.colorScheme.background);
-
- // Test the custom animation curve and duration.
- await tester.tap(find.text('Custom'));
- await tester.pumpAndSettle();
-
- await tester.tap(find.text('Switch Theme Mode'));
- await tester.pump();
- // Advance the animation by half of the custom duration.
- await tester.pump(const Duration(milliseconds: 500));
-
- // The Scaffold background color is updated.
- expect(getScaffoldMaterial().color, const Color(0xff3c3e3b));
-
- await tester.pumpAndSettle();
-
- // The Scaffold background color is now fully light.
- expect(getScaffoldMaterial().color, lightTheme.colorScheme.background);
-
- // Test the no animation style.
- await tester.tap(find.text('None'));
- await tester.pumpAndSettle();
-
- await tester.tap(find.text('Switch Theme Mode'));
- // Advance the animation by only one frame.
- await tester.pump();
-
- // The Scaffold background color is updated immediately.
- expect(getScaffoldMaterial().color, darkTheme.colorScheme.background);
- });
-}
diff --git a/examples/api/test/material/popup_menu/popup_menu.2_test.dart b/examples/api/test/material/popup_menu/popup_menu.2_test.dart
deleted file mode 100644
index e8e130c..0000000
--- a/examples/api/test/material/popup_menu/popup_menu.2_test.dart
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2014 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:flutter/material.dart';
-import 'package:flutter_api_samples/material/popup_menu/popup_menu.2.dart' as example;
-import 'package:flutter_test/flutter_test.dart';
-
-void main() {
- testWidgets('Popup animation can be customized using AnimationStyle', (WidgetTester tester) async {
- await tester.pumpWidget(
- const example.PopupMenuApp(),
- );
-
- // Test the default popup animation.
- await tester.tap(find.byIcon(Icons.more_vert));
- await tester.pump();
- // Advance the animation by half of the default duration.
- await tester.pump(const Duration(milliseconds: 100));
-
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(224.0, 130.0)));
-
- // Let the animation finish.
- await tester.pumpAndSettle();
-
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(224.0, 312.0)));
-
- // Tap outside the popup menu to close it.
- await tester.tapAt(const Offset(1, 1));
- await tester.pumpAndSettle();
-
- // Test the custom animation curve and duration.
- await tester.tap(find.text('Custom'));
- await tester.pumpAndSettle();
-
- await tester.tap(find.byIcon(Icons.more_vert));
- await tester.pump();
- // Advance the animation by one third of the custom duration.
- await tester.pump(const Duration(milliseconds: 1000));
-
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(224.0, 312.0)));
-
- // Let the animation finish.
- await tester.pumpAndSettle();
-
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(224.0, 312.0)));
-
- // Tap outside the popup menu to close it.
- await tester.tapAt(const Offset(1, 1));
- await tester.pumpAndSettle();
-
- // Test the no animation style.
- await tester.tap(find.text('None'));
- await tester.pumpAndSettle();
-
- await tester.tap(find.byIcon(Icons.more_vert));
- // Advance the animation by only one frame.
- await tester.pump();
-
- // The popup menu is shown immediately.
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(224.0, 312.0)));
- });
-}
diff --git a/packages/flutter/lib/animation.dart b/packages/flutter/lib/animation.dart
index 5df986c..24255db 100644
--- a/packages/flutter/lib/animation.dart
+++ b/packages/flutter/lib/animation.dart
@@ -165,7 +165,6 @@
export 'src/animation/animation.dart';
export 'src/animation/animation_controller.dart';
-export 'src/animation/animation_style.dart';
export 'src/animation/animations.dart';
export 'src/animation/curves.dart';
export 'src/animation/listener_helpers.dart';
diff --git a/packages/flutter/lib/src/animation/animation_style.dart b/packages/flutter/lib/src/animation/animation_style.dart
deleted file mode 100644
index e450bac..0000000
--- a/packages/flutter/lib/src/animation/animation_style.dart
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2014 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'curves.dart';
-
-/// Used to override the default parameters of an animation.
-///
-/// Currently, this class is used by the following widgets:
-/// - [ExpansionTile]
-/// - [MaterialApp]
-/// - [PopupMenuButton]
-///
-/// If [duration] and [reverseDuration] are set to [Duration.zero], the
-/// corresponding animation will be disabled.
-///
-/// All of the parameters are optional. If no parameters are specified,
-/// the default animation will be used.
-class AnimationStyle {
- /// Creates an instance of Animation Style class.
- AnimationStyle({
- this.curve,
- this.duration,
- this.reverseCurve,
- this.reverseDuration,
- });
-
- /// Creates an instance of Animation Style class with no animation.
- static AnimationStyle noAnimation = AnimationStyle(
- duration: Duration.zero,
- reverseDuration: Duration.zero,
- );
-
- /// When specified, the animation will use this curve.
- final Curve? curve;
-
- /// When specified, the animation will use this duration.
- final Duration? duration;
-
- /// When specified, the reverse animation will use this curve.
- final Curve? reverseCurve;
-
- /// When specified, the reverse animation will use this duration.
- final Duration? reverseDuration;
-}
diff --git a/packages/flutter/lib/src/material/app.dart b/packages/flutter/lib/src/material/app.dart
index 1ba8b00..7d7d426 100644
--- a/packages/flutter/lib/src/material/app.dart
+++ b/packages/flutter/lib/src/material/app.dart
@@ -184,7 +184,6 @@
/// ),
/// )
/// ```
-///
/// See also:
///
/// * [Scaffold], which provides standard app elements like an [AppBar] and a [Drawer].
@@ -247,7 +246,6 @@
'This feature was deprecated after v3.7.0-29.0.pre.'
)
this.useInheritedMediaQuery = false,
- this.themeAnimationStyle,
}) : routeInformationProvider = null,
routeInformationParser = null,
routerDelegate = null,
@@ -298,7 +296,6 @@
'This feature was deprecated after v3.7.0-29.0.pre.'
)
this.useInheritedMediaQuery = false,
- this.themeAnimationStyle,
}) : assert(routerDelegate != null || routerConfig != null),
navigatorObservers = null,
navigatorKey = null,
@@ -756,28 +753,6 @@
)
final bool useInheritedMediaQuery;
- /// Used to override the theme animation curve and duration.
- ///
- /// If [AnimationStyle.duration] is provided, it will be used to override
- /// the theme animation duration in the underlying [AnimatedTheme] widget.
- /// If it is null, then [themeAnimationDuration] will be used. Otherwise,
- /// defaults to 200ms.
- ///
- /// If [AnimationStyle.curve] is provided, it will be used to override
- /// the theme animation curve in the underlying [AnimatedTheme] widget.
- /// If it is null, then [themeAnimationCurve] will be used. Otherwise,
- /// defaults to [Curves.linear].
- ///
- /// To disable the theme animation, use [AnimationStyle.noAnimation].
- ///
- /// {@tool dartpad}
- /// This sample showcases how to override the theme animation curve and
- /// duration in the [MaterialApp] widget using [AnimationStyle].
- ///
- /// ** See code in examples/api/lib/material/app/app.0.dart **
- /// {@end-tool}
- final AnimationStyle? themeAnimationStyle;
-
@override
State<MaterialApp> createState() => _MaterialAppState();
@@ -955,34 +930,6 @@
final Color effectiveSelectionColor = theme.textSelectionTheme.selectionColor ?? theme.colorScheme.primary.withOpacity(0.40);
final Color effectiveCursorColor = theme.textSelectionTheme.cursorColor ?? theme.colorScheme.primary;
- Widget childWidget = widget.builder != null
- ? Builder(
- builder: (BuildContext context) {
- // Why are we surrounding a builder with a builder?
- //
- // The widget.builder may contain code that invokes
- // Theme.of(), which should return the theme we selected
- // above in AnimatedTheme. However, if we invoke
- // widget.builder() directly as the child of AnimatedTheme
- // then there is no Context separating them, and the
- // widget.builder() will not find the theme. Therefore, we
- // surround widget.builder with yet another builder so that
- // a context separates them and Theme.of() correctly
- // resolves to the theme we passed to AnimatedTheme.
- return widget.builder!(context, child);
- },
- )
- : child ?? const SizedBox.shrink();
-
- if (widget.themeAnimationStyle != AnimationStyle.noAnimation) {
- childWidget = AnimatedTheme(
- data: theme,
- duration: widget.themeAnimationStyle?.duration ?? widget.themeAnimationDuration,
- curve: widget.themeAnimationStyle?.curve ?? widget.themeAnimationCurve,
- child: childWidget,
- );
- }
-
return ScaffoldMessenger(
key: widget.scaffoldMessengerKey,
child: DefaultSelectionStyle(
@@ -990,9 +937,26 @@
cursorColor: effectiveCursorColor,
child: AnimatedTheme(
data: theme,
- duration: widget.themeAnimationStyle?.duration ?? widget.themeAnimationDuration,
- curve: widget.themeAnimationStyle?.curve ?? widget.themeAnimationCurve,
- child: childWidget,
+ duration: widget.themeAnimationDuration,
+ curve: widget.themeAnimationCurve,
+ child: widget.builder != null
+ ? Builder(
+ builder: (BuildContext context) {
+ // Why are we surrounding a builder with a builder?
+ //
+ // The widget.builder may contain code that invokes
+ // Theme.of(), which should return the theme we selected
+ // above in AnimatedTheme. However, if we invoke
+ // widget.builder() directly as the child of AnimatedTheme
+ // then there is no Context separating them, and the
+ // widget.builder() will not find the theme. Therefore, we
+ // surround widget.builder with yet another builder so that
+ // a context separates them and Theme.of() correctly
+ // resolves to the theme we passed to AnimatedTheme.
+ return widget.builder!(context, child);
+ },
+ )
+ : child ?? const SizedBox.shrink(),
),
),
);
diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart
index e891352..364ef59 100644
--- a/packages/flutter/lib/src/material/popup_menu.dart
+++ b/packages/flutter/lib/src/material/popup_menu.dart
@@ -816,7 +816,6 @@
this.constraints,
required this.clipBehavior,
super.settings,
- this.popUpAnimationStyle,
}) : itemSizes = List<Size?>.filled(items.length, null),
// Menus always cycle focus through their items irrespective of the
// focus traversal edge behavior set in the Navigator.
@@ -835,22 +834,18 @@
final CapturedThemes capturedThemes;
final BoxConstraints? constraints;
final Clip clipBehavior;
- final AnimationStyle? popUpAnimationStyle;
@override
Animation<double> createAnimation() {
- if (popUpAnimationStyle != AnimationStyle.noAnimation) {
- return CurvedAnimation(
- parent: super.createAnimation(),
- curve: popUpAnimationStyle?.curve ?? Curves.linear,
- reverseCurve: popUpAnimationStyle?.reverseCurve ?? const Interval(0.0, _kMenuCloseIntervalEnd),
- );
- }
- return super.createAnimation();
+ return CurvedAnimation(
+ parent: super.createAnimation(),
+ curve: Curves.linear,
+ reverseCurve: const Interval(0.0, _kMenuCloseIntervalEnd),
+ );
}
@override
- Duration get transitionDuration => popUpAnimationStyle?.duration ?? _kMenuDuration;
+ Duration get transitionDuration => _kMenuDuration;
@override
bool get barrierDismissible => true;
@@ -982,7 +977,6 @@
BoxConstraints? constraints,
Clip clipBehavior = Clip.none,
RouteSettings? routeSettings,
- AnimationStyle? popUpAnimationStyle,
}) {
assert(items.isNotEmpty);
assert(debugCheckHasMaterialLocalizations(context));
@@ -1014,7 +1008,6 @@
constraints: constraints,
clipBehavior: clipBehavior,
settings: routeSettings,
- popUpAnimationStyle: popUpAnimationStyle,
));
}
@@ -1102,13 +1095,6 @@
/// ** See code in examples/api/lib/material/popup_menu/popup_menu.1.dart **
/// {@end-tool}
///
-/// {@tool dartpad}
-/// This sample showcases how to override the [PopupMenuButton] animation
-/// curves and duration using [AnimationStyle].
-///
-/// ** See code in examples/api/lib/material/popup_menu/popup_menu.2.dart **
-/// {@end-tool}
-///
/// See also:
///
/// * [PopupMenuItem], a popup menu entry for a single value.
@@ -1143,7 +1129,6 @@
this.position,
this.clipBehavior = Clip.none,
this.useRootNavigator = false,
- this.popUpAnimationStyle,
}) : assert(
!(child != null && icon != null),
'You can only pass [child] or [icon], not both.',
@@ -1314,24 +1299,6 @@
/// Defaults to false.
final bool useRootNavigator;
- /// Used to override the default animation curves and durations of the popup
- /// menu's open and close transitions.
- ///
- /// If [AnimationStyle.curve] is provided, it will be used to override
- /// the default popup animation curve. Otherwise, defaults to [Curves.linear].
- ///
- /// If [AnimationStyle.reverseCurve] is provided, it will be used to
- /// override the default popup animation reverse curve. Otherwise, defaults to
- /// `Interval(0.0, 2.0 / 3.0)`.
- ///
- /// If [AnimationStyle.duration] is provided, it will be used to override
- /// the default popup animation duration. Otherwise, defaults to 300ms.
- ///
- /// To disable the theme animation, use [AnimationStyle.noAnimation].
- ///
- /// If this is null, then the default animation will be used.
- final AnimationStyle? popUpAnimationStyle;
-
@override
PopupMenuButtonState<T> createState() => PopupMenuButtonState<T>();
}
@@ -1389,7 +1356,6 @@
constraints: widget.constraints,
clipBehavior: widget.clipBehavior,
useRootNavigator: widget.useRootNavigator,
- popUpAnimationStyle: widget.popUpAnimationStyle,
)
.then<void>((T? newValue) {
if (!mounted) {
diff --git a/packages/flutter/test/material/app_test.dart b/packages/flutter/test/material/app_test.dart
index aadf341..e676c30 100644
--- a/packages/flutter/test/material/app_test.dart
+++ b/packages/flutter/test/material/app_test.dart
@@ -1525,71 +1525,6 @@
defaultBehavior.buildScrollbar(capturedContext, child, details);
}
}, variant: TargetPlatformVariant.all());
-
- testWidgetsWithLeakTracking('Override theme animation using AnimationStyle', (WidgetTester tester) async {
- final ThemeData lightTheme = ThemeData.light();
- final ThemeData darkTheme = ThemeData.dark();
-
- Widget buildWidget({ ThemeMode themeMode = ThemeMode.light, AnimationStyle? animationStyle }) {
- return MaterialApp(
- theme: lightTheme,
- darkTheme: darkTheme,
- themeMode: themeMode,
- themeAnimationStyle: animationStyle,
- home: const Scaffold(body: Text('body')),
- );
- }
-
- // Test the initial Scaffold background color.
- await tester.pumpWidget(buildWidget());
-
- expect(tester.widget<Material>(find.byType(Material)).color, const Color(0xfffffbfe));
-
- // Test the Scaffold background color animation from light to dark theme.
- await tester.pumpWidget(buildWidget(themeMode: ThemeMode.dark));
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 50)); // Advance animation by 50 milliseconds.
-
- // Scaffold background color is slightly updated.
- expect(tester.widget<Material>(find.byType(Material)).color, const Color(0xffc6c3c6));
-
- // Let the animation finish.
- await tester.pumpAndSettle();
-
- // Scaffold background color is fully updated to dark theme.
- expect(tester.widget<Material>(find.byType(Material)).color, const Color(0xff1c1b1f));
-
- // Reset to light theme to compare the Scaffold background color animation
- // with the default animation curve.
- await tester.pumpWidget(buildWidget());
- await tester.pumpAndSettle();
-
- // Switch to dark theme with overriden animation curve.
- await tester.pumpWidget(buildWidget(
- themeMode: ThemeMode.dark,
- animationStyle: AnimationStyle(curve: Curves.easeIn,
- )));
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 50));
-
- // Scaffold background color is slightly updated but with a different
- // color than the default animation curve.
- expect(tester.widget<Material>(find.byType(Material)).color, const Color(0xffe9e5e9));
-
- // Let the animation finish.
- await tester.pumpAndSettle();
-
- // Scaffold background color is fully updated to dark theme.
- expect(tester.widget<Material>(find.byType(Material)).color, const Color(0xff1c1b1f));
-
- // Switch from dark to light theme with overriden animation duration.
- await tester.pumpWidget(buildWidget(animationStyle: AnimationStyle.noAnimation));
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 1));
-
- expect(tester.widget<Material>(find.byType(Material)).color, isNot(const Color(0xff1c1b1f)));
- expect(tester.widget<Material>(find.byType(Material)).color, const Color(0xfffffbfe));
- });
}
class MockScrollBehavior extends ScrollBehavior {
diff --git a/packages/flutter/test/material/popup_menu_test.dart b/packages/flutter/test/material/popup_menu_test.dart
index 16bc3d8..fed0ae1 100644
--- a/packages/flutter/test/material/popup_menu_test.dart
+++ b/packages/flutter/test/material/popup_menu_test.dart
@@ -3872,90 +3872,6 @@
expect(rootObserver.menuCount, 0);
expect(nestedObserver.menuCount, 1);
});
-
- testWidgetsWithLeakTracking('Override Popup Menu animation using AnimationStyle', (WidgetTester tester) async {
- final Key targetKey = UniqueKey();
-
- Widget buildPopupMenu({ AnimationStyle? animationStyle }) {
- return MaterialApp(
- home: Material(
- child: Center(
- child: PopupMenuButton<int>(
- key: targetKey,
- popUpAnimationStyle: animationStyle,
- itemBuilder: (BuildContext context) {
- return <PopupMenuItem<int>>[
- const PopupMenuItem<int>(
- value: 1,
- child: Text('One'),
- ),
- const PopupMenuItem<int>(
- value: 2,
- child: Text('Two'),
- ),
- const PopupMenuItem<int>(
- value: 3,
- child: Text('Three'),
- ),
- ];
- },
- ),
- ),
- ),
- );
- }
-
- // Test default animation.
- await tester.pumpWidget(buildPopupMenu());
-
- await tester.tap(find.byKey(targetKey));
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 100)); // Advance the animation by 1/3 of its duration.
-
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(112.0, 80.0)));
-
- await tester.pump(const Duration(milliseconds: 100)); // Advance the animation by 2/3 of its duration.
-
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(112.0, 160.0)));
-
- await tester.pumpAndSettle(); // Advance the animation to the end.
-
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(112.0, 160.0)));
-
- // Tap outside to dismiss the menu.
- await tester.tapAt(const Offset(20.0, 20.0));
- await tester.pumpAndSettle();
-
- // Override the animation duration.
- await tester.pumpWidget(buildPopupMenu(animationStyle: AnimationStyle(duration: Duration.zero)));
-
- await tester.tap(find.byKey(targetKey));
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 1)); // Advance the animation by 1 millisecond.
-
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(112.0, 160.0)));
-
- // Tap outside to dismiss the menu.
- await tester.tapAt(const Offset(20.0, 20.0));
- await tester.pumpAndSettle();
-
- // Override the animation curve.
- await tester.pumpWidget(buildPopupMenu(animationStyle: AnimationStyle(curve: Easing.emphasizedAccelerate)));
-
- await tester.tap(find.byKey(targetKey));
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 100)); // Advance the animation by 1/3 of its duration.
-
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(32.4, 15.4)));
-
- await tester.pump(const Duration(milliseconds: 100)); // Advance the animation by 2/3 of its duration.
-
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(112.0, 72.2)));
-
- await tester.pumpAndSettle(); // Advance the animation to the end.
-
- expect(tester.getSize(find.byType(Material).last), within(distance: 0.1, from: const Size(112.0, 160.0)));
- });
}
class TestApp extends StatelessWidget {