From 0135a3310af98564bce025c6a356b72a2649e7b4 Mon Sep 17 00:00:00 2001 From: "auto-submit[bot]" <98614782+auto-submit[bot]@users.noreply.github.com> Date: Fri, 17 Nov 2023 16:59:19 +0000 Subject: [PATCH] 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, ``` --- examples/api/lib/material/app/app.0.dart | 87 ------------ .../lib/material/popup_menu/popup_menu.0.dart | 7 +- .../lib/material/popup_menu/popup_menu.1.dart | 7 +- .../lib/material/popup_menu/popup_menu.2.dart | 129 ------------------ .../api/test/material/app/app.0_test.dart | 76 ----------- .../popup_menu/popup_menu.2_test.dart | 63 --------- packages/flutter/lib/animation.dart | 1 - .../lib/src/animation/animation_style.dart | 45 ------ packages/flutter/lib/src/material/app.dart | 76 +++-------- .../flutter/lib/src/material/popup_menu.dart | 46 +------ packages/flutter/test/material/app_test.dart | 65 --------- .../test/material/popup_menu_test.dart | 84 ------------ 12 files changed, 34 insertions(+), 652 deletions(-) delete mode 100644 examples/api/lib/material/app/app.0.dart delete mode 100644 examples/api/lib/material/popup_menu/popup_menu.2.dart delete mode 100644 examples/api/test/material/app/app.0_test.dart delete mode 100644 examples/api/test/material/popup_menu/popup_menu.2_test.dart delete mode 100644 packages/flutter/lib/src/animation/animation_style.dart 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 5df0bdee35e..00000000000 --- 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 createState() => _MaterialAppExampleState(); -} - -class _MaterialAppExampleState extends State { - Set _animationStyleSelection = {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: [ - SegmentedButton( - selected: _animationStyleSelection, - onSelectionChanged: (Set 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>(((AnimationStyles, String) shirt) { - return ButtonSegment(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 cfdc80ac7fe..47f7c820dc9 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 PopupMenuExample extends StatefulWidget { } class _PopupMenuExampleState extends State { - SampleItem? selectedItem; + SampleItem? selectedMenu; @override Widget build(BuildContext context) { @@ -38,10 +38,11 @@ class _PopupMenuExampleState extends State { appBar: AppBar(title: const Text('PopupMenuButton')), body: Center( child: PopupMenuButton( - initialValue: selectedItem, + initialValue: selectedMenu, + // Callback that sets the selected popup menu item. onSelected: (SampleItem item) { setState(() { - selectedItem = item; + selectedMenu = item; }); }, itemBuilder: (BuildContext context) => >[ 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 a961d4013b5..2a3a4d6a920 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 PopupMenuExample extends StatefulWidget { } class _PopupMenuExampleState extends State { - SampleItem? selectedItem; + SampleItem? selectedMenu; @override Widget build(BuildContext context) { @@ -39,10 +39,11 @@ class _PopupMenuExampleState extends State { appBar: AppBar(title: const Text('PopupMenuButton')), body: Center( child: PopupMenuButton( - initialValue: selectedItem, + initialValue: selectedMenu, + // Callback that sets the selected popup menu item. onSelected: (SampleItem item) { setState(() { - selectedItem = item; + selectedMenu = item; }); }, itemBuilder: (BuildContext context) => >[ 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 50947b10736..00000000000 --- 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 createState() => _PopupMenuExampleState(); -} - -class _PopupMenuExampleState extends State { - Set _animationStyleSelection = {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: [ - SegmentedButton( - selected: _animationStyleSelection, - onSelectionChanged: (Set 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>(((AnimationStyles, String) shirt) { - return ButtonSegment(value: shirt.$1, label: Text(shirt.$2)); - }) - .toList(), - ), - const SizedBox(height: 10), - PopupMenuButton( - popUpAnimationStyle: _animationStyle, - icon: const Icon(Icons.more_vert), - onSelected: (Menu item) { }, - itemBuilder: (BuildContext context) => >[ - const PopupMenuItem( - value: Menu.preview, - child: ListTile( - leading: Icon(Icons.visibility_outlined), - title: Text('Preview'), - ), - ), - const PopupMenuItem( - value: Menu.share, - child: ListTile( - leading: Icon(Icons.share_outlined), - title: Text('Share'), - ), - ), - const PopupMenuItem( - value: Menu.getLink, - child: ListTile( - leading: Icon(Icons.link_outlined), - title: Text('Get link'), - ), - ), - const PopupMenuDivider(), - const PopupMenuItem( - value: Menu.remove, - child: ListTile( - leading: Icon(Icons.delete_outline), - title: Text('Remove'), - ), - ), - const PopupMenuItem( - 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 7e17e9e2840..00000000000 --- 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(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 e8e130c7dc9..00000000000 --- 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 5df986c1e16..24255db7eeb 100644 --- a/packages/flutter/lib/animation.dart +++ b/packages/flutter/lib/animation.dart @@ -165,7 +165,6 @@ export 'package:flutter/scheduler.dart' show TickerCanceled; 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 e450bac3b58..00000000000 --- 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 1ba8b001593..7d7d42687e5 100644 --- a/packages/flutter/lib/src/material/app.dart +++ b/packages/flutter/lib/src/material/app.dart @@ -184,7 +184,6 @@ enum ThemeMode { /// ), /// ) /// ``` -/// /// See also: /// /// * [Scaffold], which provides standard app elements like an [AppBar] and a [Drawer]. @@ -247,7 +246,6 @@ class MaterialApp extends StatefulWidget { '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 @@ class MaterialApp extends StatefulWidget { '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 @@ class MaterialApp extends StatefulWidget { ) 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 createState() => _MaterialAppState(); @@ -955,34 +930,6 @@ class _MaterialAppState extends State { 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 @@ class _MaterialAppState extends State { 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 e891352ac6f..364ef591fb3 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -816,7 +816,6 @@ class _PopupMenuRoute extends PopupRoute { this.constraints, required this.clipBehavior, super.settings, - this.popUpAnimationStyle, }) : itemSizes = List.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 @@ class _PopupMenuRoute extends PopupRoute { final CapturedThemes capturedThemes; final BoxConstraints? constraints; final Clip clipBehavior; - final AnimationStyle? popUpAnimationStyle; @override Animation 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 @@ Future showMenu({ BoxConstraints? constraints, Clip clipBehavior = Clip.none, RouteSettings? routeSettings, - AnimationStyle? popUpAnimationStyle, }) { assert(items.isNotEmpty); assert(debugCheckHasMaterialLocalizations(context)); @@ -1014,7 +1008,6 @@ Future showMenu({ constraints: constraints, clipBehavior: clipBehavior, settings: routeSettings, - popUpAnimationStyle: popUpAnimationStyle, )); } @@ -1102,13 +1095,6 @@ typedef PopupMenuItemBuilder = List> Function(BuildContext /// ** 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 @@ class PopupMenuButton extends StatefulWidget { 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 @@ class PopupMenuButton extends StatefulWidget { /// 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 createState() => PopupMenuButtonState(); } @@ -1389,7 +1356,6 @@ class PopupMenuButtonState extends State> { constraints: widget.constraints, clipBehavior: widget.clipBehavior, useRootNavigator: widget.useRootNavigator, - popUpAnimationStyle: widget.popUpAnimationStyle, ) .then((T? newValue) { if (!mounted) { diff --git a/packages/flutter/test/material/app_test.dart b/packages/flutter/test/material/app_test.dart index aadf3410edb..e676c30115b 100644 --- a/packages/flutter/test/material/app_test.dart +++ b/packages/flutter/test/material/app_test.dart @@ -1525,71 +1525,6 @@ void main() { 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(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(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(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(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(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(find.byType(Material)).color, isNot(const Color(0xff1c1b1f))); - expect(tester.widget(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 16bc3d894cf..fed0ae19cf0 100644 --- a/packages/flutter/test/material/popup_menu_test.dart +++ b/packages/flutter/test/material/popup_menu_test.dart @@ -3872,90 +3872,6 @@ void main() { 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( - key: targetKey, - popUpAnimationStyle: animationStyle, - itemBuilder: (BuildContext context) { - return >[ - const PopupMenuItem( - value: 1, - child: Text('One'), - ), - const PopupMenuItem( - value: 2, - child: Text('Two'), - ), - const PopupMenuItem( - 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 {