Commit 40db1e4b authored by Hans Muller's avatar Hans Muller Committed by GitHub

Added InputDecoration helperText, helperStyle (#10852)

parent b471a9cf
...@@ -144,6 +144,7 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> { ...@@ -144,6 +144,7 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
new TextFormField( new TextFormField(
decoration: const InputDecoration( decoration: const InputDecoration(
hintText: 'Tell us about yourself', hintText: 'Tell us about yourself',
helperText: 'Keep it short, this is just a demo',
labelText: 'Life story', labelText: 'Life story',
), ),
maxLines: 3, maxLines: 3,
......
...@@ -31,6 +31,8 @@ class InputDecoration { ...@@ -31,6 +31,8 @@ class InputDecoration {
this.icon, this.icon,
this.labelText, this.labelText,
this.labelStyle, this.labelStyle,
this.helperText,
this.helperStyle,
this.hintText, this.hintText,
this.hintStyle, this.hintStyle,
this.errorText, this.errorText,
...@@ -55,6 +57,8 @@ class InputDecoration { ...@@ -55,6 +57,8 @@ class InputDecoration {
}) : icon = null, }) : icon = null,
labelText = null, labelText = null,
labelStyle = null, labelStyle = null,
helperText = null,
helperStyle = null,
errorText = null, errorText = null,
errorStyle = null, errorStyle = null,
isDense = false, isDense = false,
...@@ -93,6 +97,17 @@ class InputDecoration { ...@@ -93,6 +97,17 @@ class InputDecoration {
/// input field and the current [Theme]. /// input field and the current [Theme].
final TextStyle labelStyle; final TextStyle labelStyle;
/// Text that provides context about the field’s value, such as how the value
/// will be used.
///
/// If non-null, the text is displayed below the input field, in the same
/// location as [errorText]. If a non-null [errorText] value is specified then
/// the helper text is not shown.
final String helperText;
/// The style to use for the [helperText].
final TextStyle helperStyle;
/// Text that suggests what sort of input the field accepts. /// Text that suggests what sort of input the field accepts.
/// ///
/// Displayed on top of the input field (i.e., at the same location on the /// Displayed on top of the input field (i.e., at the same location on the
...@@ -113,7 +128,7 @@ class InputDecoration { ...@@ -113,7 +128,7 @@ class InputDecoration {
/// Text that appears below the input field. /// Text that appears below the input field.
/// ///
/// If non-null the divider, that appears below the input field is red. /// If non-null, the divider that appears below the input field is red.
final String errorText; final String errorText;
/// The style to use for the [errorText]. /// The style to use for the [errorText].
...@@ -171,6 +186,8 @@ class InputDecoration { ...@@ -171,6 +186,8 @@ class InputDecoration {
Widget icon, Widget icon,
String labelText, String labelText,
TextStyle labelStyle, TextStyle labelStyle,
String helperText,
TextStyle helperStyle,
String hintText, String hintText,
TextStyle hintStyle, TextStyle hintStyle,
String errorText, String errorText,
...@@ -186,6 +203,8 @@ class InputDecoration { ...@@ -186,6 +203,8 @@ class InputDecoration {
icon: icon ?? this.icon, icon: icon ?? this.icon,
labelText: labelText ?? this.labelText, labelText: labelText ?? this.labelText,
labelStyle: labelStyle ?? this.labelStyle, labelStyle: labelStyle ?? this.labelStyle,
helperText: helperText ?? this.helperText,
helperStyle: helperStyle ?? this.helperStyle,
hintText: hintText ?? this.hintText, hintText: hintText ?? this.hintText,
hintStyle: hintStyle ?? this.hintStyle, hintStyle: hintStyle ?? this.hintStyle,
errorText: errorText ?? this.errorText, errorText: errorText ?? this.errorText,
...@@ -209,6 +228,8 @@ class InputDecoration { ...@@ -209,6 +228,8 @@ class InputDecoration {
return typedOther.icon == icon return typedOther.icon == icon
&& typedOther.labelText == labelText && typedOther.labelText == labelText
&& typedOther.labelStyle == labelStyle && typedOther.labelStyle == labelStyle
&& typedOther.helperText == helperText
&& typedOther.helperStyle == helperStyle
&& typedOther.hintText == hintText && typedOther.hintText == hintText
&& typedOther.hintStyle == hintStyle && typedOther.hintStyle == hintStyle
&& typedOther.errorText == errorText && typedOther.errorText == errorText
...@@ -228,6 +249,8 @@ class InputDecoration { ...@@ -228,6 +249,8 @@ class InputDecoration {
icon, icon,
labelText, labelText,
labelStyle, labelStyle,
helperText,
helperStyle,
hintText, hintText,
hintStyle, hintStyle,
errorText, errorText,
...@@ -249,6 +272,8 @@ class InputDecoration { ...@@ -249,6 +272,8 @@ class InputDecoration {
description.add('icon: $icon'); description.add('icon: $icon');
if (labelText != null) if (labelText != null)
description.add('labelText: "$labelText"'); description.add('labelText: "$labelText"');
if (helperText != null)
description.add('helperText: "$helperText"');
if (hintText != null) if (hintText != null)
description.add('hintText: "$hintText"'); description.add('hintText: "$hintText"');
if (errorText != null) if (errorText != null)
...@@ -390,6 +415,7 @@ class InputDecorator extends StatelessWidget { ...@@ -390,6 +415,7 @@ class InputDecorator extends StatelessWidget {
assert(!isDense || !isCollapsed); assert(!isDense || !isCollapsed);
final String labelText = decoration.labelText; final String labelText = decoration.labelText;
final String helperText = decoration.helperText;
final String hintText = decoration.hintText; final String hintText = decoration.hintText;
final String errorText = decoration.errorText; final String errorText = decoration.errorText;
...@@ -485,16 +511,20 @@ class InputDecorator extends StatelessWidget { ...@@ -485,16 +511,20 @@ class InputDecorator extends StatelessWidget {
stackChildren.add(_buildContent(borderColor, topPadding, isDense, inputChild)); stackChildren.add(_buildContent(borderColor, topPadding, isDense, inputChild));
} }
if (!isDense && errorText != null) { if (!isDense && (errorText != null || helperText != null)) {
assert(!isCollapsed); assert(!isCollapsed);
final TextStyle errorStyle = decoration.errorStyle ?? themeData.textTheme.caption.copyWith(color: themeData.errorColor); final TextStyle captionStyle = themeData.textTheme.caption;
final TextStyle subtextStyle = errorText != null
? decoration.errorStyle ?? captionStyle.copyWith(color: themeData.errorColor)
: decoration.helperStyle ?? captionStyle.copyWith(color: themeData.hintColor);
stackChildren.add(new Positioned( stackChildren.add(new Positioned(
left: 0.0, left: 0.0,
right: 0.0, right: 0.0,
bottom: 0.0, bottom: 0.0,
child: new Text( child: new Text(
errorText, errorText ?? helperText,
style: errorStyle, style: subtextStyle,
textAlign: textAlign, textAlign: textAlign,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
......
...@@ -741,6 +741,75 @@ void main() { ...@@ -741,6 +741,75 @@ void main() {
await checkText('Hello World'); await checkText('Hello World');
}); });
testWidgets('TextField errorText trumps helperText', (WidgetTester tester) async {
Widget builder() {
return const Center(
child: const Material(
child: const TextField(
decoration: const InputDecoration(
errorText: 'error text',
helperText: 'helper text',
),
),
),
);
}
await tester.pumpWidget(builder());
expect(find.text('helper text'), findsNothing);
expect(find.text('error text'), findsOneWidget);
});
testWidgets('TextField with default helperStyle', (WidgetTester tester) async {
final ThemeData themeData = new ThemeData(
hintColor: Colors.blue[500],
);
Widget builder() {
return new Center(
child: new Theme(
data: themeData,
child: const Material(
child: const TextField(
decoration: const InputDecoration(
helperText: 'helper text',
),
),
),
),
);
}
await tester.pumpWidget(builder());
final Text helperText = tester.widget(find.text('helper text'));
expect(helperText.style.color, themeData.hintColor);
expect(helperText.style.fontSize, themeData.textTheme.caption.fontSize);
});
testWidgets('TextField with specified helperStyle', (WidgetTester tester) async {
final TextStyle style = new TextStyle(
color: Colors.pink[500],
fontSize: 10.0,
);
Widget builder() {
return new Center(
child: new Material(
child: new TextField(
decoration: new InputDecoration(
helperText: 'helper text',
helperStyle: style,
),
),
),
);
}
await tester.pumpWidget(builder());
final Text helperText = tester.widget(find.text('helper text'));
expect(helperText.style, style);
});
testWidgets('TextField with default hintStyle', (WidgetTester tester) async { testWidgets('TextField with default hintStyle', (WidgetTester tester) async {
final TextStyle style = new TextStyle( final TextStyle style = new TextStyle(
color: Colors.pink[500], color: Colors.pink[500],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment