Unverified Commit de44daf1 authored by Bruno Leroux's avatar Bruno Leroux Committed by GitHub

Add a parameter to configure InputDecorator hint fade animations duration (#135211)

## Description

This PR adds a parameter to configure the input decorator hint fade transition duration.

This animation is not part of the Material specification.
Removing it was considered but it breaks internal tests (see https://github.com/flutter/flutter/pull/107406).
I also considered several ways to avoid the fade animation (setting duration to 0, removing the hint text, etc) but it breaks many existing tests that assumes the hint text to be visible.

To mitigate the issue in a non disruptive way, I set the default duration to 20ms (an arbitrary short value).

## Related Issue

Fixes https://github.com/flutter/flutter/issues/20283.

## Tests

Adds 3 tests, updates 3 tests.
parent 4204f07d
...@@ -30,6 +30,13 @@ const Duration _kTransitionDuration = Duration(milliseconds: 167); ...@@ -30,6 +30,13 @@ const Duration _kTransitionDuration = Duration(milliseconds: 167);
const Curve _kTransitionCurve = Curves.fastOutSlowIn; const Curve _kTransitionCurve = Curves.fastOutSlowIn;
const double _kFinalLabelScale = 0.75; const double _kFinalLabelScale = 0.75;
// The default duration for hint fade in/out transitions.
//
// Animating hint is not mentioned in the Material specification.
// The animation is kept for backard compatibility and a short duration
// is used to mitigate the UX impact.
const Duration _kHintFadeTransitionDuration = Duration(milliseconds: 20);
// Defines the gap in the InputDecorator's outline border where the // Defines the gap in the InputDecorator's outline border where the
// floating label will appear. // floating label will appear.
class _InputBorderGap extends ChangeNotifier { class _InputBorderGap extends ChangeNotifier {
...@@ -2192,7 +2199,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat ...@@ -2192,7 +2199,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
final String? hintText = decoration.hintText; final String? hintText = decoration.hintText;
final Widget? hint = hintText == null ? null : AnimatedOpacity( final Widget? hint = hintText == null ? null : AnimatedOpacity(
opacity: (isEmpty && !_hasInlineLabel) ? 1.0 : 0.0, opacity: (isEmpty && !_hasInlineLabel) ? 1.0 : 0.0,
duration: _kTransitionDuration, duration: decoration.hintFadeDuration ?? _kHintFadeTransitionDuration,
curve: _kTransitionCurve, curve: _kTransitionCurve,
child: Text( child: Text(
hintText, hintText,
...@@ -2571,6 +2578,7 @@ class InputDecoration { ...@@ -2571,6 +2578,7 @@ class InputDecoration {
this.hintStyle, this.hintStyle,
this.hintTextDirection, this.hintTextDirection,
this.hintMaxLines, this.hintMaxLines,
this.hintFadeDuration,
this.error, this.error,
this.errorText, this.errorText,
this.errorStyle, this.errorStyle,
...@@ -2641,6 +2649,7 @@ class InputDecoration { ...@@ -2641,6 +2649,7 @@ class InputDecoration {
helperStyle = null, helperStyle = null,
helperMaxLines = null, helperMaxLines = null,
hintMaxLines = null, hintMaxLines = null,
hintFadeDuration = null,
error = null, error = null,
errorText = null, errorText = null,
errorStyle = null, errorStyle = null,
...@@ -2854,6 +2863,12 @@ class InputDecoration { ...@@ -2854,6 +2863,12 @@ class InputDecoration {
/// used to handle the overflow when it is limited to single line. /// used to handle the overflow when it is limited to single line.
final int? hintMaxLines; final int? hintMaxLines;
/// The duration of the [hintText] fade in and fade out animations.
///
/// If null, defaults to [InputDecorationTheme.hintFadeDuration].
/// If [InputDecorationTheme.hintFadeDuration] is null defaults to 20ms.
final Duration? hintFadeDuration;
/// Optional widget that appears below the [InputDecorator.child] and the border. /// Optional widget that appears below the [InputDecorator.child] and the border.
/// ///
/// If non-null, the border's color animates to red and the [helperText] is not shown. /// If non-null, the border's color animates to red and the [helperText] is not shown.
...@@ -3507,6 +3522,7 @@ class InputDecoration { ...@@ -3507,6 +3522,7 @@ class InputDecoration {
String? hintText, String? hintText,
TextStyle? hintStyle, TextStyle? hintStyle,
TextDirection? hintTextDirection, TextDirection? hintTextDirection,
Duration? hintFadeDuration,
int? hintMaxLines, int? hintMaxLines,
Widget? error, Widget? error,
String? errorText, String? errorText,
...@@ -3561,6 +3577,7 @@ class InputDecoration { ...@@ -3561,6 +3577,7 @@ class InputDecoration {
hintStyle: hintStyle ?? this.hintStyle, hintStyle: hintStyle ?? this.hintStyle,
hintTextDirection: hintTextDirection ?? this.hintTextDirection, hintTextDirection: hintTextDirection ?? this.hintTextDirection,
hintMaxLines: hintMaxLines ?? this.hintMaxLines, hintMaxLines: hintMaxLines ?? this.hintMaxLines,
hintFadeDuration: hintFadeDuration ?? this.hintFadeDuration,
error: error ?? this.error, error: error ?? this.error,
errorText: errorText ?? this.errorText, errorText: errorText ?? this.errorText,
errorStyle: errorStyle ?? this.errorStyle, errorStyle: errorStyle ?? this.errorStyle,
...@@ -3614,6 +3631,7 @@ class InputDecoration { ...@@ -3614,6 +3631,7 @@ class InputDecoration {
helperStyle: helperStyle ?? theme.helperStyle, helperStyle: helperStyle ?? theme.helperStyle,
helperMaxLines : helperMaxLines ?? theme.helperMaxLines, helperMaxLines : helperMaxLines ?? theme.helperMaxLines,
hintStyle: hintStyle ?? theme.hintStyle, hintStyle: hintStyle ?? theme.hintStyle,
hintFadeDuration: hintFadeDuration ?? theme.hintFadeDuration,
errorStyle: errorStyle ?? theme.errorStyle, errorStyle: errorStyle ?? theme.errorStyle,
errorMaxLines: errorMaxLines ?? theme.errorMaxLines, errorMaxLines: errorMaxLines ?? theme.errorMaxLines,
floatingLabelBehavior: floatingLabelBehavior ?? theme.floatingLabelBehavior, floatingLabelBehavior: floatingLabelBehavior ?? theme.floatingLabelBehavior,
...@@ -3664,6 +3682,7 @@ class InputDecoration { ...@@ -3664,6 +3682,7 @@ class InputDecoration {
&& other.hintStyle == hintStyle && other.hintStyle == hintStyle
&& other.hintTextDirection == hintTextDirection && other.hintTextDirection == hintTextDirection
&& other.hintMaxLines == hintMaxLines && other.hintMaxLines == hintMaxLines
&& other.hintFadeDuration == hintFadeDuration
&& other.error == error && other.error == error
&& other.errorText == errorText && other.errorText == errorText
&& other.errorStyle == errorStyle && other.errorStyle == errorStyle
...@@ -3720,6 +3739,7 @@ class InputDecoration { ...@@ -3720,6 +3739,7 @@ class InputDecoration {
hintStyle, hintStyle,
hintTextDirection, hintTextDirection,
hintMaxLines, hintMaxLines,
hintFadeDuration,
error, error,
errorText, errorText,
errorStyle, errorStyle,
...@@ -3774,6 +3794,7 @@ class InputDecoration { ...@@ -3774,6 +3794,7 @@ class InputDecoration {
if (helperMaxLines != null) 'helperMaxLines: "$helperMaxLines"', if (helperMaxLines != null) 'helperMaxLines: "$helperMaxLines"',
if (hintText != null) 'hintText: "$hintText"', if (hintText != null) 'hintText: "$hintText"',
if (hintMaxLines != null) 'hintMaxLines: "$hintMaxLines"', if (hintMaxLines != null) 'hintMaxLines: "$hintMaxLines"',
if (hintFadeDuration != null) 'hintFadeDuration: "$hintFadeDuration"',
if (error != null) 'error: "$error"', if (error != null) 'error: "$error"',
if (errorText != null) 'errorText: "$errorText"', if (errorText != null) 'errorText: "$errorText"',
if (errorStyle != null) 'errorStyle: "$errorStyle"', if (errorStyle != null) 'errorStyle: "$errorStyle"',
...@@ -3836,6 +3857,7 @@ class InputDecorationTheme with Diagnosticable { ...@@ -3836,6 +3857,7 @@ class InputDecorationTheme with Diagnosticable {
this.helperStyle, this.helperStyle,
this.helperMaxLines, this.helperMaxLines,
this.hintStyle, this.hintStyle,
this.hintFadeDuration,
this.errorStyle, this.errorStyle,
this.errorMaxLines, this.errorMaxLines,
this.floatingLabelBehavior = FloatingLabelBehavior.auto, this.floatingLabelBehavior = FloatingLabelBehavior.auto,
...@@ -3906,6 +3928,9 @@ class InputDecorationTheme with Diagnosticable { ...@@ -3906,6 +3928,9 @@ class InputDecorationTheme with Diagnosticable {
/// input field and the current [Theme]. /// input field and the current [Theme].
final TextStyle? hintStyle; final TextStyle? hintStyle;
/// The duration of the [InputDecoration.hintText] fade in and fade out animations.
final Duration? hintFadeDuration;
/// {@macro flutter.material.inputDecoration.errorStyle} /// {@macro flutter.material.inputDecoration.errorStyle}
final TextStyle? errorStyle; final TextStyle? errorStyle;
...@@ -4243,6 +4268,7 @@ class InputDecorationTheme with Diagnosticable { ...@@ -4243,6 +4268,7 @@ class InputDecorationTheme with Diagnosticable {
TextStyle? helperStyle, TextStyle? helperStyle,
int? helperMaxLines, int? helperMaxLines,
TextStyle? hintStyle, TextStyle? hintStyle,
Duration? hintFadeDuration,
TextStyle? errorStyle, TextStyle? errorStyle,
int? errorMaxLines, int? errorMaxLines,
FloatingLabelBehavior? floatingLabelBehavior, FloatingLabelBehavior? floatingLabelBehavior,
...@@ -4277,6 +4303,7 @@ class InputDecorationTheme with Diagnosticable { ...@@ -4277,6 +4303,7 @@ class InputDecorationTheme with Diagnosticable {
helperStyle: helperStyle ?? this.helperStyle, helperStyle: helperStyle ?? this.helperStyle,
helperMaxLines: helperMaxLines ?? this.helperMaxLines, helperMaxLines: helperMaxLines ?? this.helperMaxLines,
hintStyle: hintStyle ?? this.hintStyle, hintStyle: hintStyle ?? this.hintStyle,
hintFadeDuration: hintFadeDuration ?? this.hintFadeDuration,
errorStyle: errorStyle ?? this.errorStyle, errorStyle: errorStyle ?? this.errorStyle,
errorMaxLines: errorMaxLines ?? this.errorMaxLines, errorMaxLines: errorMaxLines ?? this.errorMaxLines,
floatingLabelBehavior: floatingLabelBehavior ?? this.floatingLabelBehavior, floatingLabelBehavior: floatingLabelBehavior ?? this.floatingLabelBehavior,
...@@ -4326,6 +4353,7 @@ class InputDecorationTheme with Diagnosticable { ...@@ -4326,6 +4353,7 @@ class InputDecorationTheme with Diagnosticable {
helperStyle: helperStyle ?? inputDecorationTheme.helperStyle, helperStyle: helperStyle ?? inputDecorationTheme.helperStyle,
helperMaxLines: helperMaxLines ?? inputDecorationTheme.helperMaxLines, helperMaxLines: helperMaxLines ?? inputDecorationTheme.helperMaxLines,
hintStyle: hintStyle ?? inputDecorationTheme.hintStyle, hintStyle: hintStyle ?? inputDecorationTheme.hintStyle,
hintFadeDuration: hintFadeDuration ?? inputDecorationTheme.hintFadeDuration,
errorStyle: errorStyle ?? inputDecorationTheme.errorStyle, errorStyle: errorStyle ?? inputDecorationTheme.errorStyle,
errorMaxLines: errorMaxLines ?? inputDecorationTheme.errorMaxLines, errorMaxLines: errorMaxLines ?? inputDecorationTheme.errorMaxLines,
contentPadding: contentPadding ?? inputDecorationTheme.contentPadding, contentPadding: contentPadding ?? inputDecorationTheme.contentPadding,
...@@ -4385,6 +4413,7 @@ class InputDecorationTheme with Diagnosticable { ...@@ -4385,6 +4413,7 @@ class InputDecorationTheme with Diagnosticable {
border, border,
alignLabelWithHint, alignLabelWithHint,
constraints, constraints,
hintFadeDuration,
), ),
); );
...@@ -4402,6 +4431,7 @@ class InputDecorationTheme with Diagnosticable { ...@@ -4402,6 +4431,7 @@ class InputDecorationTheme with Diagnosticable {
&& other.helperStyle == helperStyle && other.helperStyle == helperStyle
&& other.helperMaxLines == helperMaxLines && other.helperMaxLines == helperMaxLines
&& other.hintStyle == hintStyle && other.hintStyle == hintStyle
&& other.hintFadeDuration == hintFadeDuration
&& other.errorStyle == errorStyle && other.errorStyle == errorStyle
&& other.errorMaxLines == errorMaxLines && other.errorMaxLines == errorMaxLines
&& other.isDense == isDense && other.isDense == isDense
...@@ -4441,6 +4471,7 @@ class InputDecorationTheme with Diagnosticable { ...@@ -4441,6 +4471,7 @@ class InputDecorationTheme with Diagnosticable {
properties.add(DiagnosticsProperty<TextStyle>('helperStyle', helperStyle, defaultValue: defaultTheme.helperStyle)); properties.add(DiagnosticsProperty<TextStyle>('helperStyle', helperStyle, defaultValue: defaultTheme.helperStyle));
properties.add(IntProperty('helperMaxLines', helperMaxLines, defaultValue: defaultTheme.helperMaxLines)); properties.add(IntProperty('helperMaxLines', helperMaxLines, defaultValue: defaultTheme.helperMaxLines));
properties.add(DiagnosticsProperty<TextStyle>('hintStyle', hintStyle, defaultValue: defaultTheme.hintStyle)); properties.add(DiagnosticsProperty<TextStyle>('hintStyle', hintStyle, defaultValue: defaultTheme.hintStyle));
properties.add(DiagnosticsProperty<Duration>('hintFadeDuration', hintFadeDuration, defaultValue: defaultTheme.hintFadeDuration));
properties.add(DiagnosticsProperty<TextStyle>('errorStyle', errorStyle, defaultValue: defaultTheme.errorStyle)); properties.add(DiagnosticsProperty<TextStyle>('errorStyle', errorStyle, defaultValue: defaultTheme.errorStyle));
properties.add(IntProperty('errorMaxLines', errorMaxLines, defaultValue: defaultTheme.errorMaxLines)); properties.add(IntProperty('errorMaxLines', errorMaxLines, defaultValue: defaultTheme.errorMaxLines));
properties.add(DiagnosticsProperty<FloatingLabelBehavior>('floatingLabelBehavior', floatingLabelBehavior, defaultValue: defaultTheme.floatingLabelBehavior)); properties.add(DiagnosticsProperty<FloatingLabelBehavior>('floatingLabelBehavior', floatingLabelBehavior, defaultValue: defaultTheme.floatingLabelBehavior));
......
...@@ -1089,14 +1089,14 @@ void runAllTests({ required bool useMaterial3 }) { ...@@ -1089,14 +1089,14 @@ void runAllTests({ required bool useMaterial3 }) {
); );
// The hint's opacity animates from 0.0 to 1.0. // The hint's opacity animates from 0.0 to 1.0.
// The animation's duration is 167ms. // The animation's default duration is 20ms.
{ {
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity50ms = getOpacity(tester, 'hint'); final double hintOpacity9ms = getOpacity(tester, 'hint');
expect(hintOpacity50ms, inExclusiveRange(0.0, 1.0)); expect(hintOpacity9ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity100ms = getOpacity(tester, 'hint'); final double hintOpacity18ms = getOpacity(tester, 'hint');
expect(hintOpacity100ms, inExclusiveRange(hintOpacity50ms, 1.0)); expect(hintOpacity18ms, inExclusiveRange(hintOpacity9ms, 1.0));
} }
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -1123,14 +1123,14 @@ void runAllTests({ required bool useMaterial3 }) { ...@@ -1123,14 +1123,14 @@ void runAllTests({ required bool useMaterial3 }) {
); );
// The hint's opacity animates from 1.0 to 0.0. // The hint's opacity animates from 1.0 to 0.0.
// The animation's duration is 167ms. // The animation's default duration is 20ms.
{ {
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity50ms = getOpacity(tester, 'hint'); final double hintOpacity9ms = getOpacity(tester, 'hint');
expect(hintOpacity50ms, inExclusiveRange(0.0, 1.0)); expect(hintOpacity9ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity100ms = getOpacity(tester, 'hint'); final double hintOpacity18ms = getOpacity(tester, 'hint');
expect(hintOpacity100ms, inExclusiveRange(0.0, hintOpacity50ms)); expect(hintOpacity18ms, inExclusiveRange(0.0, hintOpacity9ms));
} }
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -1210,6 +1210,219 @@ void runAllTests({ required bool useMaterial3 }) { ...@@ -1210,6 +1210,219 @@ void runAllTests({ required bool useMaterial3 }) {
expect(getBorderWeight(tester), 2.0); expect(getBorderWeight(tester), 2.0);
}); });
testWidgetsWithLeakTracking('InputDecorator default hint animation duration', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
labelText: 'label',
hintText: 'hint',
),
),
);
// The hint is not visible (opacity 0.0).
expect(getOpacity(tester, 'hint'), 0.0);
// Focus to show the hint.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
isFocused: true,
decoration: const InputDecoration(
labelText: 'label',
hintText: 'hint',
),
),
);
// The hint's opacity animates from 0.0 to 1.0.
// The animation's default duration is 20ms.
{
await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity9ms = getOpacity(tester, 'hint');
expect(hintOpacity9ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity18ms = getOpacity(tester, 'hint');
expect(hintOpacity18ms, inExclusiveRange(hintOpacity9ms, 1.0));
await tester.pump(const Duration(milliseconds: 9));
expect(getOpacity(tester, 'hint'), 1.0);
}
// Unfocus to hide the hint.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
labelText: 'label',
hintText: 'hint',
),
),
);
// The hint's opacity animates from 1.0 to 0.0.
// The animation's default duration is 20ms.
{
await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity9ms = getOpacity(tester, 'hint');
expect(hintOpacity9ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity18ms = getOpacity(tester, 'hint');
expect(hintOpacity18ms, inExclusiveRange(0.0, hintOpacity9ms));
await tester.pump(const Duration(milliseconds: 9));
expect(getOpacity(tester, 'hint'), 0.0);
}
});
testWidgetsWithLeakTracking('InputDecorator custom hint animation duration', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
labelText: 'label',
hintText: 'hint',
hintFadeDuration: Duration(milliseconds: 120),
),
),
);
// The hint is not visible (opacity 0.0).
expect(getOpacity(tester, 'hint'), 0.0);
// Focus to show the hint.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
isFocused: true,
decoration: const InputDecoration(
labelText: 'label',
hintText: 'hint',
hintFadeDuration: Duration(milliseconds: 120),
),
),
);
// The hint's opacity animates from 0.0 to 1.0.
// The animation's duration is set to 120ms.
{
await tester.pump(const Duration(milliseconds: 50));
final double hintOpacity50ms = getOpacity(tester, 'hint');
expect(hintOpacity50ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 50));
final double hintOpacity100ms = getOpacity(tester, 'hint');
expect(hintOpacity100ms, inExclusiveRange(hintOpacity50ms, 1.0));
await tester.pump(const Duration(milliseconds: 50));
expect(getOpacity(tester, 'hint'), 1.0);
}
// Unfocus to hide the hint.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
labelText: 'label',
hintText: 'hint',
hintFadeDuration: Duration(milliseconds: 120),
),
),
);
// The hint's opacity animates from 1.0 to 0.0.
// The animation's default duration is 20ms.
{
await tester.pump(const Duration(milliseconds: 50));
final double hintOpacity50ms = getOpacity(tester, 'hint');
expect(hintOpacity50ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 50));
final double hintOpacity100ms = getOpacity(tester, 'hint');
expect(hintOpacity100ms, inExclusiveRange(0.0, hintOpacity50ms));
await tester.pump(const Duration(milliseconds: 50));
expect(getOpacity(tester, 'hint'), 0.0);
}
});
testWidgetsWithLeakTracking('InputDecorator custom hint animation duration from theme', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
inputDecorationTheme: const InputDecorationTheme(
hintFadeDuration: Duration(milliseconds: 120),
),
isEmpty: true,
decoration: const InputDecoration(
labelText: 'label',
hintText: 'hint',
),
),
);
// The hint is not visible (opacity 0.0).
expect(getOpacity(tester, 'hint'), 0.0);
// Focus to show the hint.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
inputDecorationTheme: const InputDecorationTheme(
hintFadeDuration: Duration(milliseconds: 120),
),
isEmpty: true,
isFocused: true,
decoration: const InputDecoration(
labelText: 'label',
hintText: 'hint',
),
),
);
// The hint's opacity animates from 0.0 to 1.0.
// The animation's duration is set to 120ms.
{
await tester.pump(const Duration(milliseconds: 50));
final double hintOpacity50ms = getOpacity(tester, 'hint');
expect(hintOpacity50ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 50));
final double hintOpacity100ms = getOpacity(tester, 'hint');
expect(hintOpacity100ms, inExclusiveRange(hintOpacity50ms, 1.0));
await tester.pump(const Duration(milliseconds: 50));
expect(getOpacity(tester, 'hint'), 1.0);
}
// Unfocus to hide the hint.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
inputDecorationTheme: const InputDecorationTheme(
hintFadeDuration: Duration(milliseconds: 120),
),
isEmpty: true,
decoration: const InputDecoration(
labelText: 'label',
hintText: 'hint',
),
),
);
// The hint's opacity animates from 1.0 to 0.0.
// The animation's duration is set to 160ms.
{
await tester.pump(const Duration(milliseconds: 50));
final double hintOpacity50ms = getOpacity(tester, 'hint');
expect(hintOpacity50ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 50));
final double hintOpacity100ms = getOpacity(tester, 'hint');
expect(hintOpacity100ms, inExclusiveRange(0.0, hintOpacity50ms));
await tester.pump(const Duration(milliseconds: 50));
expect(getOpacity(tester, 'hint'), 0.0);
}
});
testWidgetsWithLeakTracking('InputDecorator with no input border', (WidgetTester tester) async { testWidgetsWithLeakTracking('InputDecorator with no input border', (WidgetTester tester) async {
// Label is visible, hint is not (opacity 0.0). // Label is visible, hint is not (opacity 0.0).
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2246,14 +2459,14 @@ void runAllTests({ required bool useMaterial3 }) { ...@@ -2246,14 +2459,14 @@ void runAllTests({ required bool useMaterial3 }) {
); );
// The hint's opacity animates from 0.0 to 1.0. // The hint's opacity animates from 0.0 to 1.0.
// The animation's duration is 167ms. // The animation's default duration is 20ms.
{ {
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity50ms = getOpacity(tester, 'hint'); final double hintOpacity9ms = getOpacity(tester, 'hint');
expect(hintOpacity50ms, inExclusiveRange(0.0, 1.0)); expect(hintOpacity9ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity100ms = getOpacity(tester, 'hint'); final double hintOpacity18ms = getOpacity(tester, 'hint');
expect(hintOpacity100ms, inExclusiveRange(hintOpacity50ms, 1.0)); expect(hintOpacity18ms, inExclusiveRange(hintOpacity9ms, 1.0));
} }
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -2281,14 +2494,14 @@ void runAllTests({ required bool useMaterial3 }) { ...@@ -2281,14 +2494,14 @@ void runAllTests({ required bool useMaterial3 }) {
); );
// The hint's opacity animates from 1.0 to 0.0. // The hint's opacity animates from 1.0 to 0.0.
// The animation's duration is 167ms. // The animation's default duration is 20ms.
{ {
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity50ms = getOpacity(tester, 'hint'); final double hintOpacity9ms = getOpacity(tester, 'hint');
expect(hintOpacity50ms, inExclusiveRange(0.0, 1.0)); expect(hintOpacity9ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity100ms = getOpacity(tester, 'hint'); final double hintOpacity18ms = getOpacity(tester, 'hint');
expect(hintOpacity100ms, inExclusiveRange(0.0, hintOpacity50ms)); expect(hintOpacity18ms, inExclusiveRange(0.0, hintOpacity9ms));
} }
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -2343,14 +2556,14 @@ void runAllTests({ required bool useMaterial3 }) { ...@@ -2343,14 +2556,14 @@ void runAllTests({ required bool useMaterial3 }) {
); );
// The hint's opacity animates from 0.0 to 1.0. // The hint's opacity animates from 0.0 to 1.0.
// The animation's duration is 167ms. // The animation's default duration is 20ms.
{ {
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity50ms = getOpacity(tester, 'hint'); final double hintOpacity9ms = getOpacity(tester, 'hint');
expect(hintOpacity50ms, inExclusiveRange(0.0, 1.0)); expect(hintOpacity9ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity100ms = getOpacity(tester, 'hint'); final double hintOpacity18ms = getOpacity(tester, 'hint');
expect(hintOpacity100ms, inExclusiveRange(hintOpacity50ms, 1.0)); expect(hintOpacity18ms, inExclusiveRange(hintOpacity9ms, 1.0));
} }
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -2378,14 +2591,14 @@ void runAllTests({ required bool useMaterial3 }) { ...@@ -2378,14 +2591,14 @@ void runAllTests({ required bool useMaterial3 }) {
); );
// The hint's opacity animates from 1.0 to 0.0. // The hint's opacity animates from 1.0 to 0.0.
// The animation's duration is 167ms. // The animation's default duration is 20ms.
{ {
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity50ms = getOpacity(tester, 'hint'); final double hintOpacity9ms = getOpacity(tester, 'hint');
expect(hintOpacity50ms, inExclusiveRange(0.0, 1.0)); expect(hintOpacity9ms, inExclusiveRange(0.0, 1.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 9));
final double hintOpacity100ms = getOpacity(tester, 'hint'); final double hintOpacity18ms = getOpacity(tester, 'hint');
expect(hintOpacity100ms, inExclusiveRange(0.0, hintOpacity50ms)); expect(hintOpacity18ms, inExclusiveRange(0.0, hintOpacity9ms));
} }
await tester.pumpAndSettle(); await tester.pumpAndSettle();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment