From d85571b46bc159882bb251fd5af195ffa4042f93 Mon Sep 17 00:00:00 2001 From: Chikamatsu Kazuya <43089218+chika3742@users.noreply.github.com> Date: Thu, 25 Apr 2024 07:44:04 +0900 Subject: [PATCH] Add support for overriding `reverseCurve` with `ExpansionTile.expansionAnimationStyle` (#147103) This PR adds support for overriding `reverseCurve` with `ExpansionTile.expansionAnimationStyle`. Closes #146760 --- .../lib/src/material/expansion_tile.dart | 18 ++++++++++++++---- .../test/material/expansion_tile_test.dart | 19 +++++++++++++++++-- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/packages/flutter/lib/src/material/expansion_tile.dart b/packages/flutter/lib/src/material/expansion_tile.dart index fab75cba946..6cd45acce55 100644 --- a/packages/flutter/lib/src/material/expansion_tile.dart +++ b/packages/flutter/lib/src/material/expansion_tile.dart @@ -543,6 +543,11 @@ class ExpansionTile extends StatefulWidget { /// from the [ExpansionTileThemeData.expansionAnimationStyle] will be used. /// Otherwise, defaults to [Curves.easeIn]. /// + /// If [AnimationStyle.reverseCurve] is provided, it will be used to override + /// the collapse animation curve. If it is null, then [AnimationStyle.reverseCurve] + /// from the [ExpansionTileThemeData.expansionAnimationStyle] will be used. + /// Otherwise, the same curve will be used as for expansion. + /// /// To disable the theme animation, use [AnimationStyle.noAnimation]. /// /// {@tool dartpad} @@ -566,11 +571,11 @@ class _ExpansionTileState extends State with SingleTickerProvider final ColorTween _headerColorTween = ColorTween(); final ColorTween _iconColorTween = ColorTween(); final ColorTween _backgroundColorTween = ColorTween(); - final CurveTween _heightFactorTween = CurveTween(curve: Curves.easeIn); + final Tween _heightFactorTween = Tween(begin: 0.0, end: 1.0); late AnimationController _animationController; late Animation _iconTurns; - late Animation _heightFactor; + late CurvedAnimation _heightFactor; late Animation _border; late Animation _headerColor; late Animation _iconColor; @@ -584,7 +589,10 @@ class _ExpansionTileState extends State with SingleTickerProvider void initState() { super.initState(); _animationController = AnimationController(duration: _kExpand, vsync: this); - _heightFactor = _animationController.drive(_heightFactorTween); + _heightFactor = CurvedAnimation( + parent: _animationController.drive(_heightFactorTween), + curve: Curves.easeIn, + ); _iconTurns = _animationController.drive(_halfTween.chain(_easeInTween)); _border = _animationController.drive(_borderTween.chain(_easeOutTween)); _headerColor = _animationController.drive(_headerColorTween.chain(_easeInTween)); @@ -862,9 +870,11 @@ class _ExpansionTileState extends State with SingleTickerProvider } void _updateHeightFactorCurve(ExpansionTileThemeData expansionTileTheme) { - _heightFactorTween.curve = widget.expansionAnimationStyle?.curve + _heightFactor.curve = widget.expansionAnimationStyle?.curve ?? expansionTileTheme.expansionAnimationStyle?.curve ?? Curves.easeIn; + _heightFactor.reverseCurve = widget.expansionAnimationStyle?.reverseCurve + ?? expansionTileTheme.expansionAnimationStyle?.reverseCurve; } @override diff --git a/packages/flutter/test/material/expansion_tile_test.dart b/packages/flutter/test/material/expansion_tile_test.dart index 536e4fd36ae..70daebbb82f 100644 --- a/packages/flutter/test/material/expansion_tile_test.dart +++ b/packages/flutter/test/material/expansion_tile_test.dart @@ -1149,7 +1149,10 @@ void main() { await tester.pumpAndSettle(); // Override the animation curve. - await tester.pumpWidget(buildExpansionTile(animationStyle: AnimationStyle(curve: Easing.emphasizedDecelerate))); + await tester.pumpWidget(buildExpansionTile(animationStyle: AnimationStyle( + curve: Easing.emphasizedDecelerate, + reverseCurve: Easing.emphasizedAccelerate, + ))); await tester.pumpAndSettle(); // Test the overridden animation curve. @@ -1167,8 +1170,20 @@ void main() { expect(getHeight(expansionTileKey), 158.0); - // Tap to collapse the ExpansionTile. + // Test the overridden reverse (collapse) animation curve. await tester.tap(find.text('title')); + await tester.pump(); + await tester.pump(const Duration(milliseconds: 50)); // Advance the animation by 1/4 of its duration. + + expect(getHeight(expansionTileKey), closeTo(98.6, 0.1)); + + await tester.pump(const Duration(milliseconds: 50)); // Advance the animation by 2/4 of its duration. + + expect(getHeight(expansionTileKey), closeTo(73.4, 0.1)); + + await tester.pumpAndSettle(); // Advance the animation to the end. + + expect(getHeight(expansionTileKey), 58.0); // Test no animation. await tester.pumpWidget(buildExpansionTile(animationStyle: AnimationStyle.noAnimation));