mirror of
https://github.com/flutter/flutter
synced 2024-10-14 04:02:56 +00:00
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);
|
||||
}
|
||||
|
||||
double get _borderWeight {
|
||||
if (decoration.isCollapsed || decoration.border == InputBorder.none || !decoration.enabled)
|
||||
return 0.0;
|
||||
return isFocused ? 2.0 : 1.0;
|
||||
}
|
||||
|
||||
Color _getBorderColor(ThemeData themeData) {
|
||||
if (!decoration.enabled) {
|
||||
if (decoration.filled == true && !decoration.border.isOutline)
|
||||
return Colors.transparent;
|
||||
return themeData.disabledColor;
|
||||
InputBorder _getDefaultBorder(ThemeData themeData) {
|
||||
Color borderColor;
|
||||
if (decoration.enabled) {
|
||||
borderColor = decoration.errorText == null
|
||||
? _getActiveColor(themeData)
|
||||
: themeData.errorColor;
|
||||
} else {
|
||||
borderColor = (decoration.filled == true && decoration.border?.isOutline != true)
|
||||
? Colors.transparent
|
||||
: themeData.disabledColor;
|
||||
}
|
||||
return decoration.errorText == null
|
||||
? _getActiveColor(themeData)
|
||||
: themeData.errorColor;
|
||||
|
||||
double borderWeight;
|
||||
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
|
||||
|
@ -1627,23 +1632,22 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
|||
),
|
||||
);
|
||||
|
||||
final InputBorder border = decoration.border.copyWith(
|
||||
borderSide: new BorderSide(
|
||||
color: _getBorderColor(themeData),
|
||||
width: _borderWeight,
|
||||
),
|
||||
);
|
||||
final bool isError = decoration.errorText != null;
|
||||
InputBorder border;
|
||||
if (!decoration.enabled)
|
||||
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
|
||||
? new DecoratedBox(
|
||||
decoration: new BoxDecoration(color: _getFillColor(themeData))
|
||||
)
|
||||
: new _BorderContainer(
|
||||
border: border,
|
||||
gap: _borderGap,
|
||||
gapAnimation: _floatingLabelController.view,
|
||||
fillColor: _getFillColor(themeData),
|
||||
);
|
||||
final Widget container = new _BorderContainer(
|
||||
border: border,
|
||||
gap: _borderGap,
|
||||
gapAnimation: _floatingLabelController.view,
|
||||
fillColor: _getFillColor(themeData),
|
||||
);
|
||||
|
||||
final TextStyle inlineLabelStyle = inlineStyle.merge(decoration.labelStyle);
|
||||
final Widget label = decoration.labelText == null ? null : new _Shaker(
|
||||
|
@ -1759,7 +1763,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
|||
if (decoration.isCollapsed) {
|
||||
floatingLabelHeight = 0.0;
|
||||
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.
|
||||
floatingLabelHeight = 4.0 + 0.75 * inlineLabelStyle.fontSize;
|
||||
if (decoration.filled == true) { // filled == null same as filled == false
|
||||
|
@ -1786,7 +1790,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
|||
isCollapsed: decoration.isCollapsed,
|
||||
floatingLabelHeight: floatingLabelHeight,
|
||||
floatingLabelProgress: _floatingLabelController.value,
|
||||
border: decoration.border,
|
||||
border: border,
|
||||
borderGap: _borderGap,
|
||||
icon: icon,
|
||||
input: widget.child,
|
||||
|
@ -1856,6 +1860,11 @@ class InputDecoration {
|
|||
this.counterStyle,
|
||||
this.filled,
|
||||
this.fillColor,
|
||||
this.errorBorder,
|
||||
this.focusedBorder,
|
||||
this.focusedErrorBorder,
|
||||
this.disabledBorder,
|
||||
this.enabledBorder,
|
||||
this.border,
|
||||
this.enabled = true,
|
||||
}) : assert(enabled != null), isCollapsed = false;
|
||||
|
@ -1891,7 +1900,12 @@ class InputDecoration {
|
|||
suffixText = null,
|
||||
suffixStyle = 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
|
||||
/// container.
|
||||
|
@ -2119,16 +2133,147 @@ class InputDecoration {
|
|||
/// [errorText], and [counterText].
|
||||
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
|
||||
/// true and bordered per the [border]. It's the area adjacent to
|
||||
/// [decoration.icon] and above the widgets that contain [helperText],
|
||||
/// [errorText], and [counterText].
|
||||
/// [InputDecoration.icon] and above the widgets that contain
|
||||
/// [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:
|
||||
///
|
||||
/// * [InputBorder.none], which doesn't draw a border.
|
||||
/// * [UnderlineInputBorder], which draws a horizontal line at the
|
||||
/// bottom of the input decorator's container.
|
||||
/// * [OutlineInputBorder], an [InputDecorator] border which draws a
|
||||
|
@ -2168,6 +2313,11 @@ class InputDecoration {
|
|||
TextStyle counterStyle,
|
||||
bool filled,
|
||||
Color fillColor,
|
||||
InputBorder errorBorder,
|
||||
InputBorder focusedBorder,
|
||||
InputBorder focusedErrorBorder,
|
||||
InputBorder disabledBorder,
|
||||
InputBorder enabledBorder,
|
||||
InputBorder border,
|
||||
bool enabled,
|
||||
}) {
|
||||
|
@ -2194,6 +2344,11 @@ class InputDecoration {
|
|||
counterStyle: counterStyle ?? this.counterStyle,
|
||||
filled: filled ?? this.filled,
|
||||
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,
|
||||
enabled: enabled ?? this.enabled,
|
||||
);
|
||||
|
@ -2218,6 +2373,11 @@ class InputDecoration {
|
|||
counterStyle: counterStyle ?? theme.counterStyle,
|
||||
filled: filled ?? theme.filled,
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
@ -2252,6 +2412,11 @@ class InputDecoration {
|
|||
&& typedOther.counterStyle == counterStyle
|
||||
&& typedOther.filled == filled
|
||||
&& typedOther.fillColor == fillColor
|
||||
&& typedOther.errorBorder == errorBorder
|
||||
&& typedOther.focusedBorder == focusedBorder
|
||||
&& typedOther.focusedErrorBorder == focusedErrorBorder
|
||||
&& typedOther.disabledBorder == disabledBorder
|
||||
&& typedOther.enabledBorder == enabledBorder
|
||||
&& typedOther.border == border
|
||||
&& typedOther.enabled == enabled;
|
||||
}
|
||||
|
@ -2265,12 +2430,12 @@ class InputDecoration {
|
|||
helperText,
|
||||
helperStyle,
|
||||
hintText,
|
||||
hintStyle,
|
||||
errorText,
|
||||
errorStyle,
|
||||
errorMaxLines,
|
||||
isDense,
|
||||
hashValues( // Over 20 fields...
|
||||
hintStyle,
|
||||
errorText,
|
||||
errorStyle,
|
||||
errorMaxLines,
|
||||
isDense,
|
||||
contentPadding,
|
||||
isCollapsed,
|
||||
prefixIcon,
|
||||
|
@ -2283,6 +2448,11 @@ class InputDecoration {
|
|||
counterStyle,
|
||||
filled,
|
||||
fillColor,
|
||||
errorBorder,
|
||||
focusedBorder,
|
||||
focusedErrorBorder,
|
||||
disabledBorder,
|
||||
enabledBorder,
|
||||
border,
|
||||
enabled,
|
||||
),
|
||||
|
@ -2332,6 +2502,16 @@ class InputDecoration {
|
|||
description.add('filled: true');
|
||||
if (fillColor != null)
|
||||
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)
|
||||
description.add('border: $border');
|
||||
if (!enabled)
|
||||
|
@ -2370,11 +2550,15 @@ class InputDecorationTheme extends Diagnosticable {
|
|||
this.counterStyle,
|
||||
this.filled = false,
|
||||
this.fillColor,
|
||||
this.border = const UnderlineInputBorder(),
|
||||
this.errorBorder,
|
||||
this.focusedBorder,
|
||||
this.focusedErrorBorder,
|
||||
this.disabledBorder,
|
||||
this.enabledBorder,
|
||||
this.border,
|
||||
}) : assert(isDense != null),
|
||||
assert(isCollapsed != null),
|
||||
assert(filled != null),
|
||||
assert(border != null);
|
||||
assert(filled != null);
|
||||
|
||||
/// The style to use for [InputDecoration.labelText] when the label is
|
||||
/// above (i.e., vertically adjacent to) the input field.
|
||||
|
@ -2476,7 +2660,124 @@ class InputDecorationTheme extends Diagnosticable {
|
|||
/// true and bordered per the [border].
|
||||
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
|
||||
/// 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.counterText].
|
||||
///
|
||||
/// The default value of this property is `const UnderlineInputBorder()`.
|
||||
///
|
||||
/// The border's bounds, i.e. the value of `border.getOuterPath()`, defines
|
||||
/// 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:
|
||||
///
|
||||
/// * [InputBorder.none], which doesn't draw a border.
|
||||
/// * [UnderlineInputBorder], which draws a horizontal line at the
|
||||
/// 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<bool>('filled', filled, defaultValue: defaultTheme.filled));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ double getBorderBottom(WidgetTester tester) {
|
|||
return box.size.height;
|
||||
}
|
||||
|
||||
BorderSide getBorderSide(WidgetTester tester) {
|
||||
InputBorder getBorder(WidgetTester tester) {
|
||||
if (!tester.any(findBorderPainter()))
|
||||
return null;
|
||||
final CustomPaint customPaint = tester.widget(findBorderPainter());
|
||||
|
@ -70,7 +70,11 @@ BorderSide getBorderSide(WidgetTester tester) {
|
|||
final dynamic/*_InputBorderTween */ inputBorderTween = inputBorderPainter.border;
|
||||
final Animation<double> animation = inputBorderPainter.borderAnimation;
|
||||
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;
|
||||
|
@ -1650,4 +1654,140 @@ void main() {
|
|||
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…
Reference in a new issue