Add support for overriding reverseCurve with ExpansionTile.expansionAnimationStyle (#147103)

This PR adds support for overriding `reverseCurve` with `ExpansionTile.expansionAnimationStyle`.

Closes #146760
This commit is contained in:
Chikamatsu Kazuya 2024-04-25 07:44:04 +09:00 committed by GitHub
parent 1df1c84dbe
commit d85571b46b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 6 deletions

View File

@ -543,6 +543,11 @@ class ExpansionTile extends StatefulWidget {
/// from the [ExpansionTileThemeData.expansionAnimationStyle] will be used. /// from the [ExpansionTileThemeData.expansionAnimationStyle] will be used.
/// Otherwise, defaults to [Curves.easeIn]. /// 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]. /// To disable the theme animation, use [AnimationStyle.noAnimation].
/// ///
/// {@tool dartpad} /// {@tool dartpad}
@ -566,11 +571,11 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider
final ColorTween _headerColorTween = ColorTween(); final ColorTween _headerColorTween = ColorTween();
final ColorTween _iconColorTween = ColorTween(); final ColorTween _iconColorTween = ColorTween();
final ColorTween _backgroundColorTween = ColorTween(); final ColorTween _backgroundColorTween = ColorTween();
final CurveTween _heightFactorTween = CurveTween(curve: Curves.easeIn); final Tween<double> _heightFactorTween = Tween<double>(begin: 0.0, end: 1.0);
late AnimationController _animationController; late AnimationController _animationController;
late Animation<double> _iconTurns; late Animation<double> _iconTurns;
late Animation<double> _heightFactor; late CurvedAnimation _heightFactor;
late Animation<ShapeBorder?> _border; late Animation<ShapeBorder?> _border;
late Animation<Color?> _headerColor; late Animation<Color?> _headerColor;
late Animation<Color?> _iconColor; late Animation<Color?> _iconColor;
@ -584,7 +589,10 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider
void initState() { void initState() {
super.initState(); super.initState();
_animationController = AnimationController(duration: _kExpand, vsync: this); _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)); _iconTurns = _animationController.drive(_halfTween.chain(_easeInTween));
_border = _animationController.drive(_borderTween.chain(_easeOutTween)); _border = _animationController.drive(_borderTween.chain(_easeOutTween));
_headerColor = _animationController.drive(_headerColorTween.chain(_easeInTween)); _headerColor = _animationController.drive(_headerColorTween.chain(_easeInTween));
@ -862,9 +870,11 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider
} }
void _updateHeightFactorCurve(ExpansionTileThemeData expansionTileTheme) { void _updateHeightFactorCurve(ExpansionTileThemeData expansionTileTheme) {
_heightFactorTween.curve = widget.expansionAnimationStyle?.curve _heightFactor.curve = widget.expansionAnimationStyle?.curve
?? expansionTileTheme.expansionAnimationStyle?.curve ?? expansionTileTheme.expansionAnimationStyle?.curve
?? Curves.easeIn; ?? Curves.easeIn;
_heightFactor.reverseCurve = widget.expansionAnimationStyle?.reverseCurve
?? expansionTileTheme.expansionAnimationStyle?.reverseCurve;
} }
@override @override

View File

@ -1149,7 +1149,10 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
// Override the animation curve. // 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(); await tester.pumpAndSettle();
// Test the overridden animation curve. // Test the overridden animation curve.
@ -1167,8 +1170,20 @@ void main() {
expect(getHeight(expansionTileKey), 158.0); 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.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. // Test no animation.
await tester.pumpWidget(buildExpansionTile(animationStyle: AnimationStyle.noAnimation)); await tester.pumpWidget(buildExpansionTile(animationStyle: AnimationStyle.noAnimation));