Textfield InputDecorator height can grow to accomodate error text (#17292)
This commit is contained in:
parent
feb16d8d01
commit
f8d0d877f5
@ -242,6 +242,7 @@ class _HelperError extends StatefulWidget {
|
|||||||
this.helperStyle,
|
this.helperStyle,
|
||||||
this.errorText,
|
this.errorText,
|
||||||
this.errorStyle,
|
this.errorStyle,
|
||||||
|
this.errorMaxLines,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final TextAlign textAlign;
|
final TextAlign textAlign;
|
||||||
@ -249,6 +250,7 @@ class _HelperError extends StatefulWidget {
|
|||||||
final TextStyle helperStyle;
|
final TextStyle helperStyle;
|
||||||
final String errorText;
|
final String errorText;
|
||||||
final TextStyle errorStyle;
|
final TextStyle errorStyle;
|
||||||
|
final int errorMaxLines;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_HelperErrorState createState() => new _HelperErrorState();
|
_HelperErrorState createState() => new _HelperErrorState();
|
||||||
@ -343,6 +345,7 @@ class _HelperErrorState extends State<_HelperError> with SingleTickerProviderSta
|
|||||||
style: widget.errorStyle,
|
style: widget.errorStyle,
|
||||||
textAlign: widget.textAlign,
|
textAlign: widget.textAlign,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: widget.errorMaxLines,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -444,7 +447,7 @@ class _Decoration {
|
|||||||
assert(floatingLabelHeight != null),
|
assert(floatingLabelHeight != null),
|
||||||
assert(floatingLabelProgress != null);
|
assert(floatingLabelProgress != null);
|
||||||
|
|
||||||
final EdgeInsets contentPadding;
|
final EdgeInsetsGeometry contentPadding;
|
||||||
final bool isCollapsed;
|
final bool isCollapsed;
|
||||||
final double floatingLabelHeight;
|
final double floatingLabelHeight;
|
||||||
final double floatingLabelProgress;
|
final double floatingLabelProgress;
|
||||||
@ -800,11 +803,21 @@ class _RenderDecoration extends RenderBox {
|
|||||||
double subtextBaseline = 0.0;
|
double subtextBaseline = 0.0;
|
||||||
double subtextHeight = 0.0;
|
double subtextHeight = 0.0;
|
||||||
if (helperError != null || counter != null) {
|
if (helperError != null || counter != null) {
|
||||||
|
boxConstraints = layoutConstraints.loosen();
|
||||||
aboveBaseline = 0.0;
|
aboveBaseline = 0.0;
|
||||||
belowBaseline = 0.0;
|
belowBaseline = 0.0;
|
||||||
layoutLineBox(helperError);
|
|
||||||
layoutLineBox(counter);
|
layoutLineBox(counter);
|
||||||
|
|
||||||
|
// The helper or error text can occupy the full width less the space
|
||||||
|
// occupied by the icon and counter.
|
||||||
|
boxConstraints = boxConstraints.copyWith(
|
||||||
|
maxWidth: boxConstraints.maxWidth
|
||||||
|
- _boxSize(icon).width
|
||||||
|
- _boxSize(counter).width
|
||||||
|
- contentPadding.horizontal,
|
||||||
|
);
|
||||||
|
layoutLineBox(helperError);
|
||||||
|
|
||||||
if (aboveBaseline + belowBaseline > 0.0) {
|
if (aboveBaseline + belowBaseline > 0.0) {
|
||||||
const double subtextGap = 8.0;
|
const double subtextGap = 8.0;
|
||||||
subtextBaseline = containerHeight + subtextGap + aboveBaseline;
|
subtextBaseline = containerHeight + subtextGap + aboveBaseline;
|
||||||
@ -1637,39 +1650,44 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
|||||||
helperStyle: _getHelperStyle(themeData),
|
helperStyle: _getHelperStyle(themeData),
|
||||||
errorText: decoration.errorText,
|
errorText: decoration.errorText,
|
||||||
errorStyle: _getErrorStyle(themeData),
|
errorStyle: _getErrorStyle(themeData),
|
||||||
|
errorMaxLines: decoration.errorMaxLines,
|
||||||
);
|
);
|
||||||
|
|
||||||
final Widget counter = decoration.counterText == null ? null :
|
final Widget counter = decoration.counterText == null ? null :
|
||||||
new Text(
|
new Text(
|
||||||
decoration.counterText,
|
decoration.counterText,
|
||||||
style: _getHelperStyle(themeData).merge(decoration.counterStyle),
|
style: _getHelperStyle(themeData).merge(decoration.counterStyle),
|
||||||
textAlign: textAlign == TextAlign.end ? TextAlign.start : TextAlign.end,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// The _Decoration widget and _RenderDecoration assume that contentPadding
|
||||||
|
// has been resolved to EdgeInsets.
|
||||||
|
final TextDirection textDirection = Directionality.of(context);
|
||||||
|
final EdgeInsets decorationContentPadding = decoration.contentPadding?.resolve(textDirection);
|
||||||
|
|
||||||
EdgeInsets contentPadding;
|
EdgeInsets contentPadding;
|
||||||
double floatingLabelHeight;
|
double floatingLabelHeight;
|
||||||
if (decoration.isCollapsed) {
|
if (decoration.isCollapsed) {
|
||||||
floatingLabelHeight = 0.0;
|
floatingLabelHeight = 0.0;
|
||||||
contentPadding = decoration.contentPadding ?? EdgeInsets.zero;
|
contentPadding = decorationContentPadding ?? EdgeInsets.zero;
|
||||||
} else if (!decoration.border.isOutline) {
|
} else if (!decoration.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
|
||||||
contentPadding = decoration.contentPadding ?? (decorationIsDense
|
contentPadding = decorationContentPadding ?? (decorationIsDense
|
||||||
? const EdgeInsets.fromLTRB(12.0, 8.0, 12.0, 8.0)
|
? const EdgeInsets.fromLTRB(12.0, 8.0, 12.0, 8.0)
|
||||||
: const EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 12.0));
|
: const EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 12.0));
|
||||||
} else {
|
} else {
|
||||||
// Not left or right padding for underline borders that aren't filled
|
// Not left or right padding for underline borders that aren't filled
|
||||||
// is a small concession to backwards compatibility. This eliminates
|
// is a small concession to backwards compatibility. This eliminates
|
||||||
// the most noticeable layout change introduced by #13734.
|
// the most noticeable layout change introduced by #13734.
|
||||||
contentPadding = decoration.contentPadding ?? (decorationIsDense
|
contentPadding = decorationContentPadding ?? (decorationIsDense
|
||||||
? const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0)
|
? const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0)
|
||||||
: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 12.0));
|
: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 12.0));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
floatingLabelHeight = 0.0;
|
floatingLabelHeight = 0.0;
|
||||||
contentPadding = decoration.contentPadding ?? (decorationIsDense
|
contentPadding = decorationContentPadding ?? (decorationIsDense
|
||||||
? const EdgeInsets.fromLTRB(12.0, 20.0, 12.0, 12.0)
|
? const EdgeInsets.fromLTRB(12.0, 20.0, 12.0, 12.0)
|
||||||
: const EdgeInsets.fromLTRB(12.0, 24.0, 12.0, 16.0));
|
: const EdgeInsets.fromLTRB(12.0, 24.0, 12.0, 16.0));
|
||||||
}
|
}
|
||||||
@ -1720,8 +1738,9 @@ class InputDecoration {
|
|||||||
///
|
///
|
||||||
/// Unless specified by [ThemeData.inputDecorationTheme],
|
/// Unless specified by [ThemeData.inputDecorationTheme],
|
||||||
/// [InputDecorator] defaults [isDense] to true, and [filled] to false,
|
/// [InputDecorator] defaults [isDense] to true, and [filled] to false,
|
||||||
/// Similarly, the default border is an instance of [UnderlineInputBorder].
|
/// and [maxLines] to 1. The default border is an instance
|
||||||
/// If [border] is [InputBorder.none] then no border is drawn.
|
/// of [UnderlineInputBorder]. If [border] is [InputBorder.none] then
|
||||||
|
/// no border is drawn.
|
||||||
///
|
///
|
||||||
/// The [enabled] argument must not be null.
|
/// The [enabled] argument must not be null.
|
||||||
const InputDecoration({
|
const InputDecoration({
|
||||||
@ -1734,6 +1753,7 @@ class InputDecoration {
|
|||||||
this.hintStyle,
|
this.hintStyle,
|
||||||
this.errorText,
|
this.errorText,
|
||||||
this.errorStyle,
|
this.errorStyle,
|
||||||
|
this.errorMaxLines,
|
||||||
this.isDense,
|
this.isDense,
|
||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
this.prefixIcon,
|
this.prefixIcon,
|
||||||
@ -1770,6 +1790,7 @@ class InputDecoration {
|
|||||||
helperStyle = null,
|
helperStyle = null,
|
||||||
errorText = null,
|
errorText = null,
|
||||||
errorStyle = null,
|
errorStyle = null,
|
||||||
|
errorMaxLines = null,
|
||||||
isDense = false,
|
isDense = false,
|
||||||
contentPadding = EdgeInsets.zero,
|
contentPadding = EdgeInsets.zero,
|
||||||
isCollapsed = true,
|
isCollapsed = true,
|
||||||
@ -1861,6 +1882,16 @@ class InputDecoration {
|
|||||||
/// input field and the current [Theme].
|
/// input field and the current [Theme].
|
||||||
final TextStyle errorStyle;
|
final TextStyle errorStyle;
|
||||||
|
|
||||||
|
|
||||||
|
/// The maximum number of lines the [errorText] can occupy.
|
||||||
|
///
|
||||||
|
/// Defaults to null, which means that the [errorText] will be limited
|
||||||
|
/// to a single line with [TextOverflow.ellipsis].
|
||||||
|
///
|
||||||
|
/// This value is passed along to the [Text.maxLines] attribute
|
||||||
|
/// of the [Text] widget used to display the error.
|
||||||
|
final int errorMaxLines;
|
||||||
|
|
||||||
/// Whether the input [child] is part of a dense form (i.e., uses less vertical
|
/// Whether the input [child] is part of a dense form (i.e., uses less vertical
|
||||||
/// space).
|
/// space).
|
||||||
///
|
///
|
||||||
@ -1877,7 +1908,7 @@ class InputDecoration {
|
|||||||
/// By default the `contentPadding` reflects [isDense] and the type of the
|
/// By default the `contentPadding` reflects [isDense] and the type of the
|
||||||
/// [border]. If [isCollapsed] is true then `contentPadding` is
|
/// [border]. If [isCollapsed] is true then `contentPadding` is
|
||||||
/// [EdgeInsets.zero].
|
/// [EdgeInsets.zero].
|
||||||
final EdgeInsets contentPadding;
|
final EdgeInsetsGeometry contentPadding;
|
||||||
|
|
||||||
/// Whether the decoration is the same size as the input field.
|
/// Whether the decoration is the same size as the input field.
|
||||||
///
|
///
|
||||||
@ -2024,8 +2055,9 @@ class InputDecoration {
|
|||||||
TextStyle hintStyle,
|
TextStyle hintStyle,
|
||||||
String errorText,
|
String errorText,
|
||||||
TextStyle errorStyle,
|
TextStyle errorStyle,
|
||||||
|
int errorMaxLines,
|
||||||
bool isDense,
|
bool isDense,
|
||||||
EdgeInsets contentPadding,
|
EdgeInsetsGeometry contentPadding,
|
||||||
Widget prefixIcon,
|
Widget prefixIcon,
|
||||||
String prefixText,
|
String prefixText,
|
||||||
TextStyle prefixStyle,
|
TextStyle prefixStyle,
|
||||||
@ -2049,6 +2081,7 @@ class InputDecoration {
|
|||||||
hintStyle: hintStyle ?? this.hintStyle,
|
hintStyle: hintStyle ?? this.hintStyle,
|
||||||
errorText: errorText ?? this.errorText,
|
errorText: errorText ?? this.errorText,
|
||||||
errorStyle: errorStyle ?? this.errorStyle,
|
errorStyle: errorStyle ?? this.errorStyle,
|
||||||
|
errorMaxLines: errorMaxLines ?? this.errorMaxLines,
|
||||||
isDense: isDense ?? this.isDense,
|
isDense: isDense ?? this.isDense,
|
||||||
contentPadding: contentPadding ?? this.contentPadding,
|
contentPadding: contentPadding ?? this.contentPadding,
|
||||||
prefixIcon: prefixIcon ?? this.prefixIcon,
|
prefixIcon: prefixIcon ?? this.prefixIcon,
|
||||||
@ -2077,6 +2110,7 @@ class InputDecoration {
|
|||||||
helperStyle: helperStyle ?? theme.helperStyle,
|
helperStyle: helperStyle ?? theme.helperStyle,
|
||||||
hintStyle: hintStyle ?? theme.hintStyle,
|
hintStyle: hintStyle ?? theme.hintStyle,
|
||||||
errorStyle: errorStyle ?? theme.errorStyle,
|
errorStyle: errorStyle ?? theme.errorStyle,
|
||||||
|
errorMaxLines: errorMaxLines ?? theme.errorMaxLines,
|
||||||
isDense: isDense ?? theme.isDense,
|
isDense: isDense ?? theme.isDense,
|
||||||
contentPadding: contentPadding ?? theme.contentPadding,
|
contentPadding: contentPadding ?? theme.contentPadding,
|
||||||
prefixStyle: prefixStyle ?? theme.prefixStyle,
|
prefixStyle: prefixStyle ?? theme.prefixStyle,
|
||||||
@ -2104,6 +2138,7 @@ class InputDecoration {
|
|||||||
&& typedOther.hintStyle == hintStyle
|
&& typedOther.hintStyle == hintStyle
|
||||||
&& typedOther.errorText == errorText
|
&& typedOther.errorText == errorText
|
||||||
&& typedOther.errorStyle == errorStyle
|
&& typedOther.errorStyle == errorStyle
|
||||||
|
&& typedOther.errorMaxLines == errorMaxLines
|
||||||
&& typedOther.isDense == isDense
|
&& typedOther.isDense == isDense
|
||||||
&& typedOther.contentPadding == contentPadding
|
&& typedOther.contentPadding == contentPadding
|
||||||
&& typedOther.isCollapsed == isCollapsed
|
&& typedOther.isCollapsed == isCollapsed
|
||||||
@ -2129,11 +2164,12 @@ class InputDecoration {
|
|||||||
labelStyle,
|
labelStyle,
|
||||||
helperText,
|
helperText,
|
||||||
helperStyle,
|
helperStyle,
|
||||||
hashValues( // Over 20 fields...
|
|
||||||
hintText,
|
hintText,
|
||||||
|
hashValues( // Over 20 fields...
|
||||||
hintStyle,
|
hintStyle,
|
||||||
errorText,
|
errorText,
|
||||||
errorStyle,
|
errorStyle,
|
||||||
|
errorMaxLines,
|
||||||
isDense,
|
isDense,
|
||||||
contentPadding,
|
contentPadding,
|
||||||
isCollapsed,
|
isCollapsed,
|
||||||
@ -2166,6 +2202,10 @@ class InputDecoration {
|
|||||||
description.add('hintText: "$hintText"');
|
description.add('hintText: "$hintText"');
|
||||||
if (errorText != null)
|
if (errorText != null)
|
||||||
description.add('errorText: "$errorText"');
|
description.add('errorText: "$errorText"');
|
||||||
|
if (errorStyle != null)
|
||||||
|
description.add('errorStyle: "$errorStyle"');
|
||||||
|
if (errorMaxLines != null)
|
||||||
|
description.add('errorMaxLines: "$errorMaxLines"');
|
||||||
if (isDense ?? false)
|
if (isDense ?? false)
|
||||||
description.add('isDense: $isDense');
|
description.add('isDense: $isDense');
|
||||||
if (contentPadding != null)
|
if (contentPadding != null)
|
||||||
@ -2221,6 +2261,7 @@ class InputDecorationTheme extends Diagnosticable {
|
|||||||
this.helperStyle,
|
this.helperStyle,
|
||||||
this.hintStyle,
|
this.hintStyle,
|
||||||
this.errorStyle,
|
this.errorStyle,
|
||||||
|
this.errorMaxLines,
|
||||||
this.isDense: false,
|
this.isDense: false,
|
||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
this.isCollapsed: false,
|
this.isCollapsed: false,
|
||||||
@ -2264,6 +2305,15 @@ class InputDecorationTheme extends Diagnosticable {
|
|||||||
/// input field and the current [Theme].
|
/// input field and the current [Theme].
|
||||||
final TextStyle errorStyle;
|
final TextStyle errorStyle;
|
||||||
|
|
||||||
|
/// The maximum number of lines the [errorText] can occupy.
|
||||||
|
///
|
||||||
|
/// Defaults to null, which means that the [errorText] will be limited
|
||||||
|
/// to a single line with [TextOverflow.ellipsis].
|
||||||
|
///
|
||||||
|
/// This value is passed along to the [Text.maxLines] attribute
|
||||||
|
/// of the [Text] widget used to display the error.
|
||||||
|
final int errorMaxLines;
|
||||||
|
|
||||||
/// Whether the input decorator's child is part of a dense form (i.e., uses
|
/// Whether the input decorator's child is part of a dense form (i.e., uses
|
||||||
/// less vertical space).
|
/// less vertical space).
|
||||||
///
|
///
|
||||||
@ -2282,7 +2332,7 @@ class InputDecorationTheme extends Diagnosticable {
|
|||||||
/// By default the `contentPadding` reflects [isDense] and the type of the
|
/// By default the `contentPadding` reflects [isDense] and the type of the
|
||||||
/// [border]. If [isCollapsed] is true then `contentPadding` is
|
/// [border]. If [isCollapsed] is true then `contentPadding` is
|
||||||
/// [EdgeInsets.zero].
|
/// [EdgeInsets.zero].
|
||||||
final EdgeInsets contentPadding;
|
final EdgeInsetsGeometry contentPadding;
|
||||||
|
|
||||||
/// Whether the decoration is the same size as the input field.
|
/// Whether the decoration is the same size as the input field.
|
||||||
///
|
///
|
||||||
@ -2355,6 +2405,7 @@ class InputDecorationTheme extends Diagnosticable {
|
|||||||
properties.add(new DiagnosticsProperty<TextStyle>('helperStyle', helperStyle, defaultValue: defaultTheme.helperStyle));
|
properties.add(new DiagnosticsProperty<TextStyle>('helperStyle', helperStyle, defaultValue: defaultTheme.helperStyle));
|
||||||
properties.add(new DiagnosticsProperty<TextStyle>('hintStyle', hintStyle, defaultValue: defaultTheme.hintStyle));
|
properties.add(new DiagnosticsProperty<TextStyle>('hintStyle', hintStyle, defaultValue: defaultTheme.hintStyle));
|
||||||
properties.add(new DiagnosticsProperty<TextStyle>('errorStyle', errorStyle, defaultValue: defaultTheme.errorStyle));
|
properties.add(new DiagnosticsProperty<TextStyle>('errorStyle', errorStyle, defaultValue: defaultTheme.errorStyle));
|
||||||
|
properties.add(new DiagnosticsProperty<int>('errorMaxLines', errorMaxLines, defaultValue: defaultTheme.errorMaxLines));
|
||||||
properties.add(new DiagnosticsProperty<bool>('isDense', isDense, defaultValue: defaultTheme.isDense));
|
properties.add(new DiagnosticsProperty<bool>('isDense', isDense, defaultValue: defaultTheme.isDense));
|
||||||
properties.add(new DiagnosticsProperty<EdgeInsets>('contentPadding', contentPadding, defaultValue: defaultTheme.contentPadding));
|
properties.add(new DiagnosticsProperty<EdgeInsets>('contentPadding', contentPadding, defaultValue: defaultTheme.contentPadding));
|
||||||
properties.add(new DiagnosticsProperty<bool>('isCollapsed', isCollapsed, defaultValue: defaultTheme.isCollapsed));
|
properties.add(new DiagnosticsProperty<bool>('isCollapsed', isCollapsed, defaultValue: defaultTheme.isCollapsed));
|
||||||
|
@ -596,6 +596,82 @@ void main() {
|
|||||||
expect(tester.getTopRight(find.text('counter')), const Offset(788.0, 56.0));
|
expect(tester.getTopRight(find.text('counter')), const Offset(788.0, 56.0));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('InputDecoration errorMaxLines', (WidgetTester tester) async {
|
||||||
|
const String kError1 = 'e0';
|
||||||
|
const String kError2 = 'e0\ne1';
|
||||||
|
const String kError3 = 'e0\ne1\ne2';
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
isEmpty: true,
|
||||||
|
// isFocused: false (default)
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'label',
|
||||||
|
helperText: 'helper',
|
||||||
|
errorText: kError3,
|
||||||
|
errorMaxLines: 3,
|
||||||
|
filled: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Overall height for this InputDecorator is 100dps:
|
||||||
|
//
|
||||||
|
// 12 - top padding
|
||||||
|
// 12 - floating label (ahem font size 16dps * 0.75 = 12)
|
||||||
|
// 4 - floating label / input text gap
|
||||||
|
// 16 - input text (ahem font size 16dps)
|
||||||
|
// 12 - bottom padding
|
||||||
|
// 8 - below the border padding
|
||||||
|
// 36 - error text (3 lines, ahem font size 12dps)
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 100.0));
|
||||||
|
expect(tester.getTopLeft(find.text(kError3)), const Offset(12.0, 64.0));
|
||||||
|
expect(tester.getBottomLeft(find.text(kError3)), const Offset(12.0, 100.0));
|
||||||
|
|
||||||
|
// Overall height for this InputDecorator is 12 less than the first
|
||||||
|
// one, 88dps, because errorText only occupies two lines.
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
isEmpty: true,
|
||||||
|
// isFocused: false (default)
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'label',
|
||||||
|
helperText: 'helper',
|
||||||
|
errorText: kError2,
|
||||||
|
errorMaxLines: 3,
|
||||||
|
filled: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 88.0));
|
||||||
|
expect(tester.getTopLeft(find.text(kError2)), const Offset(12.0, 64.0));
|
||||||
|
expect(tester.getBottomLeft(find.text(kError2)), const Offset(12.0, 88.0));
|
||||||
|
|
||||||
|
// Overall height for this InputDecorator is 24 less than the first
|
||||||
|
// one, 88dps, because errorText only occupies one line.
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
isEmpty: true,
|
||||||
|
// isFocused: false (default)
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'label',
|
||||||
|
helperText: 'helper',
|
||||||
|
errorText: kError1,
|
||||||
|
errorMaxLines: 3,
|
||||||
|
filled: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 76.0));
|
||||||
|
expect(tester.getTopLeft(find.text(kError1)), const Offset(12.0, 64.0));
|
||||||
|
expect(tester.getBottomLeft(find.text(kError1)), const Offset(12.0, 76.0));
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('InputDecorator prefix/suffix', (WidgetTester tester) async {
|
testWidgets('InputDecorator prefix/suffix', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
buildInputDecorator(
|
buildInputDecorator(
|
||||||
@ -760,6 +836,46 @@ void main() {
|
|||||||
expect(tester.getTopRight(find.text('text')).dx, lessThanOrEqualTo(tester.getTopLeft(find.text('p')).dx));
|
expect(tester.getTopRight(find.text('text')).dx, lessThanOrEqualTo(tester.getTopLeft(find.text('p')).dx));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('InputDecorator contentPadding RTL layout', (WidgetTester tester) async {
|
||||||
|
// LTR: content left edge is contentPadding.start: 40.0
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
// isEmpty: false (default)
|
||||||
|
// isFocused: false (default)
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
contentPadding: const EdgeInsetsDirectional.only(start: 40.0, top: 12.0, bottom: 12.0),
|
||||||
|
labelText: 'label',
|
||||||
|
hintText: 'hint',
|
||||||
|
filled: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
|
||||||
|
expect(tester.getTopLeft(find.text('text')).dx, 40.0);
|
||||||
|
expect(tester.getTopLeft(find.text('label')).dx, 40.0);
|
||||||
|
expect(tester.getTopLeft(find.text('hint')).dx, 40.0);
|
||||||
|
|
||||||
|
// RTL: content right edge is 800 - contentPadding.start: 760.0.
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildInputDecorator(
|
||||||
|
// isEmpty: false (default)
|
||||||
|
isFocused: true, // label is floating, still adjusted for contentPadding
|
||||||
|
textDirection: TextDirection.rtl,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
contentPadding: const EdgeInsetsDirectional.only(start: 40.0, top: 12.0, bottom: 12.0),
|
||||||
|
labelText: 'label',
|
||||||
|
hintText: 'hint',
|
||||||
|
filled: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
|
||||||
|
expect(tester.getTopRight(find.text('text')).dx, 760.0);
|
||||||
|
expect(tester.getTopRight(find.text('label')).dx, 760.0);
|
||||||
|
expect(tester.getTopRight(find.text('hint')).dx, 760.0);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('InputDecorator prefix/suffix dense layout', (WidgetTester tester) async {
|
testWidgets('InputDecorator prefix/suffix dense layout', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
buildInputDecorator(
|
buildInputDecorator(
|
||||||
@ -1194,6 +1310,7 @@ void main() {
|
|||||||
helperStyle: themeStyle,
|
helperStyle: themeStyle,
|
||||||
hintStyle: themeStyle,
|
hintStyle: themeStyle,
|
||||||
errorStyle: themeStyle,
|
errorStyle: themeStyle,
|
||||||
|
errorMaxLines: 4,
|
||||||
isDense: true,
|
isDense: true,
|
||||||
contentPadding: const EdgeInsets.all(1.0),
|
contentPadding: const EdgeInsets.all(1.0),
|
||||||
prefixStyle: themeStyle,
|
prefixStyle: themeStyle,
|
||||||
@ -1209,6 +1326,7 @@ void main() {
|
|||||||
expect(decoration.helperStyle, decorationStyle);
|
expect(decoration.helperStyle, decorationStyle);
|
||||||
expect(decoration.hintStyle, decorationStyle);
|
expect(decoration.hintStyle, decorationStyle);
|
||||||
expect(decoration.errorStyle, decorationStyle);
|
expect(decoration.errorStyle, decorationStyle);
|
||||||
|
expect(decoration.errorMaxLines, 4);
|
||||||
expect(decoration.isDense, false);
|
expect(decoration.isDense, false);
|
||||||
expect(decoration.contentPadding, const EdgeInsets.all(4.0));
|
expect(decoration.contentPadding, const EdgeInsets.all(4.0));
|
||||||
expect(decoration.prefixStyle, decorationStyle);
|
expect(decoration.prefixStyle, decorationStyle);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user