Extend InputDecoration borders for disabled/error/focused states (#19694)
Added five InputBorder properties to InputDecoration etc so that apps can control the appearance of an InputDecorator's border: errorBorder, focusedBorder, focusedErrorBorder, disabledBorder, enabledBorder.
This commit is contained in:
parent
56800d8fa1
commit
0863367c6e
@ -1591,21 +1591,26 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
|||||||
return themeData.textTheme.caption.copyWith(color: color).merge(decoration.errorStyle);
|
return themeData.textTheme.caption.copyWith(color: color).merge(decoration.errorStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
double get _borderWeight {
|
InputBorder _getDefaultBorder(ThemeData themeData) {
|
||||||
if (decoration.isCollapsed || decoration.border == InputBorder.none || !decoration.enabled)
|
Color borderColor;
|
||||||
return 0.0;
|
if (decoration.enabled) {
|
||||||
return isFocused ? 2.0 : 1.0;
|
borderColor = decoration.errorText == null
|
||||||
}
|
? _getActiveColor(themeData)
|
||||||
|
: themeData.errorColor;
|
||||||
Color _getBorderColor(ThemeData themeData) {
|
} else {
|
||||||
if (!decoration.enabled) {
|
borderColor = (decoration.filled == true && decoration.border?.isOutline != true)
|
||||||
if (decoration.filled == true && !decoration.border.isOutline)
|
? Colors.transparent
|
||||||
return Colors.transparent;
|
: themeData.disabledColor;
|
||||||
return themeData.disabledColor;
|
|
||||||
}
|
}
|
||||||
return decoration.errorText == null
|
|
||||||
? _getActiveColor(themeData)
|
double borderWeight;
|
||||||
: themeData.errorColor;
|
if (decoration.isCollapsed || decoration?.border == InputBorder.none || !decoration.enabled)
|
||||||
|
borderWeight = 0.0;
|
||||||
|
else
|
||||||
|
borderWeight = isFocused ? 2.0 : 1.0;
|
||||||
|
|
||||||
|
final InputBorder border = decoration.border ?? const UnderlineInputBorder();
|
||||||
|
return border.copyWith(borderSide: new BorderSide(color: borderColor, width: borderWeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -1627,23 +1632,22 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final InputBorder border = decoration.border.copyWith(
|
final bool isError = decoration.errorText != null;
|
||||||
borderSide: new BorderSide(
|
InputBorder border;
|
||||||
color: _getBorderColor(themeData),
|
if (!decoration.enabled)
|
||||||
width: _borderWeight,
|
border = isError ? decoration.errorBorder : decoration.disabledBorder;
|
||||||
),
|
else if (isFocused)
|
||||||
);
|
border = isError ? decoration.focusedErrorBorder : decoration.focusedBorder;
|
||||||
|
else
|
||||||
|
border = isError ? decoration.errorBorder : decoration.enabledBorder;
|
||||||
|
border ??= _getDefaultBorder(themeData);
|
||||||
|
|
||||||
final Widget container = border == null
|
final Widget container = new _BorderContainer(
|
||||||
? new DecoratedBox(
|
border: border,
|
||||||
decoration: new BoxDecoration(color: _getFillColor(themeData))
|
gap: _borderGap,
|
||||||
)
|
gapAnimation: _floatingLabelController.view,
|
||||||
: new _BorderContainer(
|
fillColor: _getFillColor(themeData),
|
||||||
border: border,
|
);
|
||||||
gap: _borderGap,
|
|
||||||
gapAnimation: _floatingLabelController.view,
|
|
||||||
fillColor: _getFillColor(themeData),
|
|
||||||
);
|
|
||||||
|
|
||||||
final TextStyle inlineLabelStyle = inlineStyle.merge(decoration.labelStyle);
|
final TextStyle inlineLabelStyle = inlineStyle.merge(decoration.labelStyle);
|
||||||
final Widget label = decoration.labelText == null ? null : new _Shaker(
|
final Widget label = decoration.labelText == null ? null : new _Shaker(
|
||||||
@ -1759,7 +1763,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
|||||||
if (decoration.isCollapsed) {
|
if (decoration.isCollapsed) {
|
||||||
floatingLabelHeight = 0.0;
|
floatingLabelHeight = 0.0;
|
||||||
contentPadding = decorationContentPadding ?? EdgeInsets.zero;
|
contentPadding = decorationContentPadding ?? EdgeInsets.zero;
|
||||||
} else if (!decoration.border.isOutline) {
|
} else if (!border.isOutline) {
|
||||||
// 4.0: the vertical gap between the inline elements and the floating label.
|
// 4.0: the vertical gap between the inline elements and the floating label.
|
||||||
floatingLabelHeight = 4.0 + 0.75 * inlineLabelStyle.fontSize;
|
floatingLabelHeight = 4.0 + 0.75 * inlineLabelStyle.fontSize;
|
||||||
if (decoration.filled == true) { // filled == null same as filled == false
|
if (decoration.filled == true) { // filled == null same as filled == false
|
||||||
@ -1786,7 +1790,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
|||||||
isCollapsed: decoration.isCollapsed,
|
isCollapsed: decoration.isCollapsed,
|
||||||
floatingLabelHeight: floatingLabelHeight,
|
floatingLabelHeight: floatingLabelHeight,
|
||||||
floatingLabelProgress: _floatingLabelController.value,
|
floatingLabelProgress: _floatingLabelController.value,
|
||||||
border: decoration.border,
|
border: border,
|
||||||
borderGap: _borderGap,
|
borderGap: _borderGap,
|
||||||
icon: icon,
|
icon: icon,
|
||||||
input: widget.child,
|
input: widget.child,
|
||||||
@ -1856,6 +1860,11 @@ class InputDecoration {
|
|||||||
this.counterStyle,
|
this.counterStyle,
|
||||||
this.filled,
|
this.filled,
|
||||||
this.fillColor,
|
this.fillColor,
|
||||||
|
this.errorBorder,
|
||||||
|
this.focusedBorder,
|
||||||
|
this.focusedErrorBorder,
|
||||||
|
this.disabledBorder,
|
||||||
|
this.enabledBorder,
|
||||||
this.border,
|
this.border,
|
||||||
this.enabled = true,
|
this.enabled = true,
|
||||||
}) : assert(enabled != null), isCollapsed = false;
|
}) : assert(enabled != null), isCollapsed = false;
|
||||||
@ -1891,7 +1900,12 @@ class InputDecoration {
|
|||||||
suffixText = null,
|
suffixText = null,
|
||||||
suffixStyle = null,
|
suffixStyle = null,
|
||||||
counterText = null,
|
counterText = null,
|
||||||
counterStyle = null;
|
counterStyle = null,
|
||||||
|
errorBorder = null,
|
||||||
|
focusedBorder = null,
|
||||||
|
focusedErrorBorder = null,
|
||||||
|
disabledBorder = null,
|
||||||
|
enabledBorder = null;
|
||||||
|
|
||||||
/// An icon to show before the input field and outside of the decoration's
|
/// An icon to show before the input field and outside of the decoration's
|
||||||
/// container.
|
/// container.
|
||||||
@ -2119,16 +2133,147 @@ class InputDecoration {
|
|||||||
/// [errorText], and [counterText].
|
/// [errorText], and [counterText].
|
||||||
final Color fillColor;
|
final Color fillColor;
|
||||||
|
|
||||||
/// The border to draw around the decoration's container.
|
/// The border to display when the [InputDecorator] does not have the focus and
|
||||||
|
/// is showing an error.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
/// * [InputDecorator.isFocused], which is true if the [InputDecorator]'s child
|
||||||
|
/// has the focus.
|
||||||
|
/// * [InputDecoration.errorText], the error shown by the [InputDecorator], if non-null.
|
||||||
|
/// * [border], for a description of where the [InputDecorator] border appears.
|
||||||
|
/// * [UnderlineInputBorder], an [InputDecorator] border which draws a horizontal
|
||||||
|
/// line at the bottom of the input decorator's container.
|
||||||
|
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||||
|
/// rounded rectangle around the input decorator's container.
|
||||||
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
|
/// * [focusedBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [focusedErrorBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [disabledBorder], displayed when [InputDecoration.enabled] is false
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [enabledBorder], displayed when [InputDecoration.enabled] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
final InputBorder errorBorder;
|
||||||
|
|
||||||
|
/// The border to display when the [InputDecorator] has the focus and is not
|
||||||
|
/// showing an error.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [InputDecorator.isFocused], which is true if the [InputDecorator]'s child
|
||||||
|
/// has the focus.
|
||||||
|
/// * [InputDecoration.errorText], the error shown by the [InputDecorator], if non-null.
|
||||||
|
/// * [border], for a description of where the [InputDecorator] border appears.
|
||||||
|
/// * [UnderlineInputBorder], an [InputDecorator] border which draws a horizontal
|
||||||
|
/// line at the bottom of the input decorator's container.
|
||||||
|
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||||
|
/// rounded rectangle around the input decorator's container.
|
||||||
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
|
/// * [errorBorder], displayed when [InputDecorator.isFocused] is false
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [focusedErrorBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [disabledBorder], displayed when [InputDecoration.enabled] is false
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [enabledBorder], displayed when [InputDecoration.enabled] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
final InputBorder focusedBorder;
|
||||||
|
|
||||||
|
/// The border to display when the [InputDecorator] has the focus and is
|
||||||
|
/// showing an error.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [InputDecorator.isFocused], which is true if the [InputDecorator]'s child
|
||||||
|
/// has the focus.
|
||||||
|
/// * [InputDecoration.errorText], the error shown by the [InputDecorator], if non-null.
|
||||||
|
/// * [border], for a description of where the [InputDecorator] border appears.
|
||||||
|
/// * [UnderlineInputBorder], an [InputDecorator] border which draws a horizontal
|
||||||
|
/// line at the bottom of the input decorator's container.
|
||||||
|
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||||
|
/// rounded rectangle around the input decorator's container.
|
||||||
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
|
/// * [errorBorder], displayed when [InputDecorator.isFocused] is false
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [focusedBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [disabledBorder], displayed when [InputDecoration.enabled] is false
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [enabledBorder], displayed when [InputDecoration.enabled] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
final InputBorder focusedErrorBorder;
|
||||||
|
|
||||||
|
/// The border to display when the [InputDecorator] is disabled and is not
|
||||||
|
/// showing an error.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [InputDecoration.enabled], which is false if the [InputDecorator] is disabled.
|
||||||
|
/// * [InputDecoration.errorText], the error shown by the [InputDecorator], if non-null.
|
||||||
|
/// * [border], for a description of where the [InputDecorator] border appears.
|
||||||
|
/// * [UnderlineInputBorder], an [InputDecorator] border which draws a horizontal
|
||||||
|
/// line at the bottom of the input decorator's container.
|
||||||
|
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||||
|
/// rounded rectangle around the input decorator's container.
|
||||||
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
|
/// * [errorBorder], displayed when [InputDecorator.isFocused] is false
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [focusedBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [focusedErrorBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [enabledBorder], displayed when [InputDecoration.enabled] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
final InputBorder disabledBorder;
|
||||||
|
|
||||||
|
/// The border to display when the [InputDecorator] is enabled and is not
|
||||||
|
/// showing an error.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [InputDecoration.enabled], which is false if the [InputDecorator] is disabled.
|
||||||
|
/// * [InputDecoration.errorText], the error shown by the [InputDecorator], if non-null.
|
||||||
|
/// * [border], for a description of where the [InputDecorator] border appears.
|
||||||
|
/// * [UnderlineInputBorder], an [InputDecorator] border which draws a horizontal
|
||||||
|
/// line at the bottom of the input decorator's container.
|
||||||
|
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||||
|
/// rounded rectangle around the input decorator's container.
|
||||||
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
|
/// * [errorBorder], displayed when [InputDecorator.isFocused] is false
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [focusedBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [focusedErrorBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [disabledBorder], displayed when [InputDecoration.enabled] is false
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
final InputBorder enabledBorder;
|
||||||
|
|
||||||
|
/// The shape of the border to draw around the decoration's container.
|
||||||
///
|
///
|
||||||
/// The decoration's container is the area which is filled if [isFilled] is
|
/// The decoration's container is the area which is filled if [isFilled] is
|
||||||
/// true and bordered per the [border]. It's the area adjacent to
|
/// true and bordered per the [border]. It's the area adjacent to
|
||||||
/// [decoration.icon] and above the widgets that contain [helperText],
|
/// [InputDecoration.icon] and above the widgets that contain
|
||||||
/// [errorText], and [counterText].
|
/// [InputDecoration.helperText], [InputDecoration.errorText], and
|
||||||
|
/// [InputDecoration.counterText].
|
||||||
///
|
///
|
||||||
/// The default value of this property is `const UnderlineInputBorder()`.
|
/// The border's bounds, i.e. the value of `border.getOuterPath()`, define
|
||||||
|
/// the area to be filled.
|
||||||
|
///
|
||||||
|
/// This property is only used when the appropriate one of [errorBorder],
|
||||||
|
/// [focusedBorder], [focusedErrorBorder], [disabledBorder], or [enabledBorder]
|
||||||
|
/// is not specified. This border's [InputBorder.borderSide] property is
|
||||||
|
/// configured by the InputDecorator, depending on the values of
|
||||||
|
/// [InputDecoration.errorText], [InputDecoration.enabled],
|
||||||
|
/// [InputDecorator.isFocused and the current [Theme].
|
||||||
|
///
|
||||||
|
/// Typically one of [UnderlineInputBorder] or [OutlineInputBorder].
|
||||||
|
/// If null, InputDecorator's default is `const UnderlineInputBorder()`.
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
/// * [UnderlineInputBorder], which draws a horizontal line at the
|
/// * [UnderlineInputBorder], which draws a horizontal line at the
|
||||||
/// bottom of the input decorator's container.
|
/// bottom of the input decorator's container.
|
||||||
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||||
@ -2168,6 +2313,11 @@ class InputDecoration {
|
|||||||
TextStyle counterStyle,
|
TextStyle counterStyle,
|
||||||
bool filled,
|
bool filled,
|
||||||
Color fillColor,
|
Color fillColor,
|
||||||
|
InputBorder errorBorder,
|
||||||
|
InputBorder focusedBorder,
|
||||||
|
InputBorder focusedErrorBorder,
|
||||||
|
InputBorder disabledBorder,
|
||||||
|
InputBorder enabledBorder,
|
||||||
InputBorder border,
|
InputBorder border,
|
||||||
bool enabled,
|
bool enabled,
|
||||||
}) {
|
}) {
|
||||||
@ -2194,6 +2344,11 @@ class InputDecoration {
|
|||||||
counterStyle: counterStyle ?? this.counterStyle,
|
counterStyle: counterStyle ?? this.counterStyle,
|
||||||
filled: filled ?? this.filled,
|
filled: filled ?? this.filled,
|
||||||
fillColor: fillColor ?? this.fillColor,
|
fillColor: fillColor ?? this.fillColor,
|
||||||
|
errorBorder: errorBorder ?? this.errorBorder,
|
||||||
|
focusedBorder: focusedBorder ?? this.focusedBorder,
|
||||||
|
focusedErrorBorder: focusedErrorBorder ?? this.focusedErrorBorder,
|
||||||
|
disabledBorder: disabledBorder ?? this.disabledBorder,
|
||||||
|
enabledBorder: enabledBorder ?? this.enabledBorder,
|
||||||
border: border ?? this.border,
|
border: border ?? this.border,
|
||||||
enabled: enabled ?? this.enabled,
|
enabled: enabled ?? this.enabled,
|
||||||
);
|
);
|
||||||
@ -2218,6 +2373,11 @@ class InputDecoration {
|
|||||||
counterStyle: counterStyle ?? theme.counterStyle,
|
counterStyle: counterStyle ?? theme.counterStyle,
|
||||||
filled: filled ?? theme.filled,
|
filled: filled ?? theme.filled,
|
||||||
fillColor: fillColor ?? theme.fillColor,
|
fillColor: fillColor ?? theme.fillColor,
|
||||||
|
errorBorder: errorBorder ?? theme.errorBorder,
|
||||||
|
focusedBorder: focusedBorder ?? theme.focusedBorder,
|
||||||
|
focusedErrorBorder: focusedErrorBorder ?? theme.focusedErrorBorder,
|
||||||
|
disabledBorder: disabledBorder ?? theme.disabledBorder,
|
||||||
|
enabledBorder: enabledBorder ?? theme.enabledBorder,
|
||||||
border: border ?? theme.border,
|
border: border ?? theme.border,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -2252,6 +2412,11 @@ class InputDecoration {
|
|||||||
&& typedOther.counterStyle == counterStyle
|
&& typedOther.counterStyle == counterStyle
|
||||||
&& typedOther.filled == filled
|
&& typedOther.filled == filled
|
||||||
&& typedOther.fillColor == fillColor
|
&& typedOther.fillColor == fillColor
|
||||||
|
&& typedOther.errorBorder == errorBorder
|
||||||
|
&& typedOther.focusedBorder == focusedBorder
|
||||||
|
&& typedOther.focusedErrorBorder == focusedErrorBorder
|
||||||
|
&& typedOther.disabledBorder == disabledBorder
|
||||||
|
&& typedOther.enabledBorder == enabledBorder
|
||||||
&& typedOther.border == border
|
&& typedOther.border == border
|
||||||
&& typedOther.enabled == enabled;
|
&& typedOther.enabled == enabled;
|
||||||
}
|
}
|
||||||
@ -2265,12 +2430,12 @@ class InputDecoration {
|
|||||||
helperText,
|
helperText,
|
||||||
helperStyle,
|
helperStyle,
|
||||||
hintText,
|
hintText,
|
||||||
|
hintStyle,
|
||||||
|
errorText,
|
||||||
|
errorStyle,
|
||||||
|
errorMaxLines,
|
||||||
|
isDense,
|
||||||
hashValues( // Over 20 fields...
|
hashValues( // Over 20 fields...
|
||||||
hintStyle,
|
|
||||||
errorText,
|
|
||||||
errorStyle,
|
|
||||||
errorMaxLines,
|
|
||||||
isDense,
|
|
||||||
contentPadding,
|
contentPadding,
|
||||||
isCollapsed,
|
isCollapsed,
|
||||||
prefixIcon,
|
prefixIcon,
|
||||||
@ -2283,6 +2448,11 @@ class InputDecoration {
|
|||||||
counterStyle,
|
counterStyle,
|
||||||
filled,
|
filled,
|
||||||
fillColor,
|
fillColor,
|
||||||
|
errorBorder,
|
||||||
|
focusedBorder,
|
||||||
|
focusedErrorBorder,
|
||||||
|
disabledBorder,
|
||||||
|
enabledBorder,
|
||||||
border,
|
border,
|
||||||
enabled,
|
enabled,
|
||||||
),
|
),
|
||||||
@ -2332,6 +2502,16 @@ class InputDecoration {
|
|||||||
description.add('filled: true');
|
description.add('filled: true');
|
||||||
if (fillColor != null)
|
if (fillColor != null)
|
||||||
description.add('fillColor: $fillColor');
|
description.add('fillColor: $fillColor');
|
||||||
|
if (errorBorder != null)
|
||||||
|
description.add('errorBorder: $errorBorder');
|
||||||
|
if (focusedBorder != null)
|
||||||
|
description.add('focusedBorder: $focusedBorder');
|
||||||
|
if (focusedErrorBorder != null)
|
||||||
|
description.add('focusedErrorBorder: $focusedErrorBorder');
|
||||||
|
if (disabledBorder != null)
|
||||||
|
description.add('disabledBorder: $disabledBorder');
|
||||||
|
if (enabledBorder != null)
|
||||||
|
description.add('enabledBorder: $enabledBorder');
|
||||||
if (border != null)
|
if (border != null)
|
||||||
description.add('border: $border');
|
description.add('border: $border');
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
@ -2370,11 +2550,15 @@ class InputDecorationTheme extends Diagnosticable {
|
|||||||
this.counterStyle,
|
this.counterStyle,
|
||||||
this.filled = false,
|
this.filled = false,
|
||||||
this.fillColor,
|
this.fillColor,
|
||||||
this.border = const UnderlineInputBorder(),
|
this.errorBorder,
|
||||||
|
this.focusedBorder,
|
||||||
|
this.focusedErrorBorder,
|
||||||
|
this.disabledBorder,
|
||||||
|
this.enabledBorder,
|
||||||
|
this.border,
|
||||||
}) : assert(isDense != null),
|
}) : assert(isDense != null),
|
||||||
assert(isCollapsed != null),
|
assert(isCollapsed != null),
|
||||||
assert(filled != null),
|
assert(filled != null);
|
||||||
assert(border != null);
|
|
||||||
|
|
||||||
/// The style to use for [InputDecoration.labelText] when the label is
|
/// The style to use for [InputDecoration.labelText] when the label is
|
||||||
/// above (i.e., vertically adjacent to) the input field.
|
/// above (i.e., vertically adjacent to) the input field.
|
||||||
@ -2476,7 +2660,124 @@ class InputDecorationTheme extends Diagnosticable {
|
|||||||
/// true and bordered per the [border].
|
/// true and bordered per the [border].
|
||||||
final Color fillColor;
|
final Color fillColor;
|
||||||
|
|
||||||
/// The border to draw around the decoration's container.
|
/// The border to display when the [InputDecorator] does not have the focus and
|
||||||
|
/// is showing an error.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
/// * [InputDecorator.isFocused], which is true if the [InputDecorator]'s child
|
||||||
|
/// has the focus.
|
||||||
|
/// * [InputDecoration.errorText], the error shown by the [InputDecorator], if non-null.
|
||||||
|
/// * [border], for a description of where the [InputDecorator] border appears.
|
||||||
|
/// * [UnderlineInputBorder], an [InputDecorator] border which draws a horizontal
|
||||||
|
/// line at the bottom of the input decorator's container.
|
||||||
|
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||||
|
/// rounded rectangle around the input decorator's container.
|
||||||
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
|
/// * [focusedBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [focusedErrorBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [disabledBorder], displayed when [InputDecoration.enabled] is false
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [enabledBorder], displayed when [InputDecoration.enabled] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
final InputBorder errorBorder;
|
||||||
|
|
||||||
|
/// The border to display when the [InputDecorator] has the focus and is not
|
||||||
|
/// showing an error.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [InputDecorator.isFocused], which is true if the [InputDecorator]'s child
|
||||||
|
/// has the focus.
|
||||||
|
/// * [InputDecoration.errorText], the error shown by the [InputDecorator], if non-null.
|
||||||
|
/// * [border], for a description of where the [InputDecorator] border appears.
|
||||||
|
/// * [UnderlineInputBorder], an [InputDecorator] border which draws a horizontal
|
||||||
|
/// line at the bottom of the input decorator's container.
|
||||||
|
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||||
|
/// rounded rectangle around the input decorator's container.
|
||||||
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
|
/// * [errorBorder], displayed when [InputDecorator.isFocused] is false
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [focusedErrorBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [disabledBorder], displayed when [InputDecoration.enabled] is false
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [enabledBorder], displayed when [InputDecoration.enabled] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
final InputBorder focusedBorder;
|
||||||
|
|
||||||
|
/// The border to display when the [InputDecorator] has the focus and is
|
||||||
|
/// showing an error.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [InputDecorator.isFocused], which is true if the [InputDecorator]'s child
|
||||||
|
/// has the focus.
|
||||||
|
/// * [InputDecoration.errorText], the error shown by the [InputDecorator], if non-null.
|
||||||
|
/// * [border], for a description of where the [InputDecorator] border appears.
|
||||||
|
/// * [UnderlineInputBorder], an [InputDecorator] border which draws a horizontal
|
||||||
|
/// line at the bottom of the input decorator's container.
|
||||||
|
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||||
|
/// rounded rectangle around the input decorator's container.
|
||||||
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
|
/// * [errorBorder], displayed when [InputDecorator.isFocused] is false
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [focusedBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [disabledBorder], displayed when [InputDecoration.enabled] is false
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [enabledBorder], displayed when [InputDecoration.enabled] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
final InputBorder focusedErrorBorder;
|
||||||
|
|
||||||
|
/// The border to display when the [InputDecorator] is disabled and is not
|
||||||
|
/// showing an error.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [InputDecoration.enabled], which is false if the [InputDecorator] is disabled.
|
||||||
|
/// * [InputDecoration.errorText], the error shown by the [InputDecorator], if non-null.
|
||||||
|
/// * [border], for a description of where the [InputDecorator] border appears.
|
||||||
|
/// * [UnderlineInputBorder], an [InputDecorator] border which draws a horizontal
|
||||||
|
/// line at the bottom of the input decorator's container.
|
||||||
|
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||||
|
/// rounded rectangle around the input decorator's container.
|
||||||
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
|
/// * [errorBorder], displayed when [InputDecorator.isFocused] is false
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [focusedBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [focusedErrorBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [enabledBorder], displayed when [InputDecoration.enabled] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
final InputBorder disabledBorder;
|
||||||
|
|
||||||
|
/// The border to display when the [InputDecorator] is enabled and is not
|
||||||
|
/// showing an error.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [InputDecoration.enabled], which is false if the [InputDecorator] is disabled.
|
||||||
|
/// * [InputDecoration.errorText], the error shown by the [InputDecorator], if non-null.
|
||||||
|
/// * [border], for a description of where the [InputDecorator] border appears.
|
||||||
|
/// * [UnderlineInputBorder], an [InputDecorator] border which draws a horizontal
|
||||||
|
/// line at the bottom of the input decorator's container.
|
||||||
|
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||||
|
/// rounded rectangle around the input decorator's container.
|
||||||
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
|
/// * [errorBorder], displayed when [InputDecorator.isFocused] is false
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [focusedBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
/// * [focusedErrorBorder], displayed when [InputDecorator.isFocused] is true
|
||||||
|
/// and [InputDecoration.errorText] is non-null.
|
||||||
|
/// * [disabledBorder], displayed when [InputDecoration.enabled] is false
|
||||||
|
/// and [InputDecoration.errorText] is null.
|
||||||
|
final InputBorder enabledBorder;
|
||||||
|
|
||||||
|
/// The shape of the border to draw around the decoration's container.
|
||||||
///
|
///
|
||||||
/// The decoration's container is the area which is filled if [isFilled] is
|
/// The decoration's container is the area which is filled if [isFilled] is
|
||||||
/// true and bordered per the [border]. It's the area adjacent to
|
/// true and bordered per the [border]. It's the area adjacent to
|
||||||
@ -2484,12 +2785,21 @@ class InputDecorationTheme extends Diagnosticable {
|
|||||||
/// [InputDecoration.helperText], [InputDecoration.errorText], and
|
/// [InputDecoration.helperText], [InputDecoration.errorText], and
|
||||||
/// [InputDecoration.counterText].
|
/// [InputDecoration.counterText].
|
||||||
///
|
///
|
||||||
/// The default value of this property is `const UnderlineInputBorder()`.
|
/// The border's bounds, i.e. the value of `border.getOuterPath()`, define
|
||||||
///
|
|
||||||
/// The border's bounds, i.e. the value of `border.getOuterPath()`, defines
|
|
||||||
/// the area to be filled.
|
/// the area to be filled.
|
||||||
///
|
///
|
||||||
|
/// This property is only used when the appropriate one of [errorBorder],
|
||||||
|
/// [focusedBorder], [focusedErrorBorder], [disabledBorder], or [enabledBorder]
|
||||||
|
/// is not specified. This border's [InputBorder.borderSide] property is
|
||||||
|
/// configured by the InputDecorator, depending on the values of
|
||||||
|
/// [InputDecoration.errorText], [InputDecoration.enabled],
|
||||||
|
/// [InputDecorator.isFocused and the current [Theme].
|
||||||
|
///
|
||||||
|
/// Typically one of [UnderlineInputBorder] or [OutlineInputBorder].
|
||||||
|
/// If null, InputDecorator's default is `const UnderlineInputBorder()`.
|
||||||
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
|
///
|
||||||
/// * [InputBorder.none], which doesn't draw a border.
|
/// * [InputBorder.none], which doesn't draw a border.
|
||||||
/// * [UnderlineInputBorder], which draws a horizontal line at the
|
/// * [UnderlineInputBorder], which draws a horizontal line at the
|
||||||
/// bottom of the input decorator's container.
|
/// bottom of the input decorator's container.
|
||||||
@ -2514,6 +2824,11 @@ class InputDecorationTheme extends Diagnosticable {
|
|||||||
properties.add(new DiagnosticsProperty<TextStyle>('counterStyle', counterStyle, defaultValue: defaultTheme.counterStyle));
|
properties.add(new DiagnosticsProperty<TextStyle>('counterStyle', counterStyle, defaultValue: defaultTheme.counterStyle));
|
||||||
properties.add(new DiagnosticsProperty<bool>('filled', filled, defaultValue: defaultTheme.filled));
|
properties.add(new DiagnosticsProperty<bool>('filled', filled, defaultValue: defaultTheme.filled));
|
||||||
properties.add(new DiagnosticsProperty<Color>('fillColor', fillColor, defaultValue: defaultTheme.fillColor));
|
properties.add(new DiagnosticsProperty<Color>('fillColor', fillColor, defaultValue: defaultTheme.fillColor));
|
||||||
|
properties.add(new DiagnosticsProperty<InputBorder>('errorBorder', errorBorder, defaultValue: defaultTheme.errorBorder));
|
||||||
|
properties.add(new DiagnosticsProperty<InputBorder>('focusedBorder', focusedBorder, defaultValue: defaultTheme.focusedErrorBorder));
|
||||||
|
properties.add(new DiagnosticsProperty<InputBorder>('focusedErrorborder', focusedErrorBorder, defaultValue: defaultTheme.focusedErrorBorder));
|
||||||
|
properties.add(new DiagnosticsProperty<InputBorder>('disabledBorder', disabledBorder, defaultValue: defaultTheme.disabledBorder));
|
||||||
|
properties.add(new DiagnosticsProperty<InputBorder>('enabledBorder', enabledBorder, defaultValue: defaultTheme.enabledBorder));
|
||||||
properties.add(new DiagnosticsProperty<InputBorder>('border', border, defaultValue: defaultTheme.border));
|
properties.add(new DiagnosticsProperty<InputBorder>('border', border, defaultValue: defaultTheme.border));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ double getBorderBottom(WidgetTester tester) {
|
|||||||
return box.size.height;
|
return box.size.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
BorderSide getBorderSide(WidgetTester tester) {
|
InputBorder getBorder(WidgetTester tester) {
|
||||||
if (!tester.any(findBorderPainter()))
|
if (!tester.any(findBorderPainter()))
|
||||||
return null;
|
return null;
|
||||||
final CustomPaint customPaint = tester.widget(findBorderPainter());
|
final CustomPaint customPaint = tester.widget(findBorderPainter());
|
||||||
@ -70,7 +70,11 @@ BorderSide getBorderSide(WidgetTester tester) {
|
|||||||
final dynamic/*_InputBorderTween */ inputBorderTween = inputBorderPainter.border;
|
final dynamic/*_InputBorderTween */ inputBorderTween = inputBorderPainter.border;
|
||||||
final Animation<double> animation = inputBorderPainter.borderAnimation;
|
final Animation<double> animation = inputBorderPainter.borderAnimation;
|
||||||
final dynamic/*_InputBorder */ border = inputBorderTween.evaluate(animation);
|
final dynamic/*_InputBorder */ border = inputBorderTween.evaluate(animation);
|
||||||
return border.borderSide;
|
return border;
|
||||||
|
}
|
||||||
|
|
||||||
|
BorderSide getBorderSide(WidgetTester tester) {
|
||||||
|
return getBorder(tester)?.borderSide;
|
||||||
}
|
}
|
||||||
|
|
||||||
double getBorderWeight(WidgetTester tester) => getBorderSide(tester)?.width;
|
double getBorderWeight(WidgetTester tester) => getBorderSide(tester)?.width;
|
||||||
@ -1650,4 +1654,140 @@ void main() {
|
|||||||
contains('contentPadding: EdgeInsetsDirectional(5.0, 0.0, 0.0, 0.0)'),
|
contains('contentPadding: EdgeInsetsDirectional(5.0, 0.0, 0.0, 0.0)'),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('InputDecoration borders', (WidgetTester tester) async {
|
||||||
|
const InputBorder errorBorder = OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: Colors.red, width: 1.5),
|
||||||
|
);
|
||||||
|
const InputBorder focusedBorder = OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: Colors.green, width: 4.0),
|
||||||
|
);
|
||||||
|
const InputBorder focusedErrorBorder = OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: Colors.teal, width: 5.0),
|
||||||
|
);
|
||||||
|
const InputBorder disabledBorder = OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: Colors.grey, width: 0.0),
|
||||||
|
);
|
||||||
|
const InputBorder enabledBorder = OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: Colors.blue, width: 2.5),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
// isFocused: false (default)
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
// errorText: null (default)
|
||||||
|
// enabled: true (default)
|
||||||
|
errorBorder: errorBorder,
|
||||||
|
focusedBorder: focusedBorder,
|
||||||
|
focusedErrorBorder: focusedErrorBorder,
|
||||||
|
disabledBorder: disabledBorder,
|
||||||
|
enabledBorder: enabledBorder,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(getBorder(tester), enabledBorder);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
isFocused: true,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
// errorText: null (default)
|
||||||
|
// enabled: true (default)
|
||||||
|
errorBorder: errorBorder,
|
||||||
|
focusedBorder: focusedBorder,
|
||||||
|
focusedErrorBorder: focusedErrorBorder,
|
||||||
|
disabledBorder: disabledBorder,
|
||||||
|
enabledBorder: enabledBorder,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle(); // border changes are animated
|
||||||
|
expect(getBorder(tester), focusedBorder);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
isFocused: true,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
errorText: 'error',
|
||||||
|
// enabled: true (default)
|
||||||
|
errorBorder: errorBorder,
|
||||||
|
focusedBorder: focusedBorder,
|
||||||
|
focusedErrorBorder: focusedErrorBorder,
|
||||||
|
disabledBorder: disabledBorder,
|
||||||
|
enabledBorder: enabledBorder,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle(); // border changes are animated
|
||||||
|
expect(getBorder(tester), focusedErrorBorder);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
// isFocused: false (default)
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
errorText: 'error',
|
||||||
|
// enabled: true (default)
|
||||||
|
errorBorder: errorBorder,
|
||||||
|
focusedBorder: focusedBorder,
|
||||||
|
focusedErrorBorder: focusedErrorBorder,
|
||||||
|
disabledBorder: disabledBorder,
|
||||||
|
enabledBorder: enabledBorder,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle(); // border changes are animated
|
||||||
|
expect(getBorder(tester), errorBorder);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
// isFocused: false (default)
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
errorText: 'error',
|
||||||
|
enabled: false,
|
||||||
|
errorBorder: errorBorder,
|
||||||
|
focusedBorder: focusedBorder,
|
||||||
|
focusedErrorBorder: focusedErrorBorder,
|
||||||
|
disabledBorder: disabledBorder,
|
||||||
|
enabledBorder: enabledBorder,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle(); // border changes are animated
|
||||||
|
expect(getBorder(tester), errorBorder);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
// isFocused: false (default)
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
// errorText: false (default)
|
||||||
|
enabled: false,
|
||||||
|
errorBorder: errorBorder,
|
||||||
|
focusedBorder: focusedBorder,
|
||||||
|
focusedErrorBorder: focusedErrorBorder,
|
||||||
|
disabledBorder: disabledBorder,
|
||||||
|
enabledBorder: enabledBorder,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle(); // border changes are animated
|
||||||
|
expect(getBorder(tester), disabledBorder);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
isFocused: true,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
// errorText: null (default)
|
||||||
|
enabled: false,
|
||||||
|
errorBorder: errorBorder,
|
||||||
|
focusedBorder: focusedBorder,
|
||||||
|
focusedErrorBorder: focusedErrorBorder,
|
||||||
|
disabledBorder: disabledBorder,
|
||||||
|
enabledBorder: enabledBorder,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle(); // border changes are animated
|
||||||
|
expect(getBorder(tester), disabledBorder);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user