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));
......
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