Commit 114335df authored by Trevor Wang's avatar Trevor Wang Committed by xster

Support TextField multi-line hint text #20941 (#24976)

parent 65df90d8
...@@ -233,7 +233,7 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> { ...@@ -233,7 +233,7 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
TextFormField( TextFormField(
decoration: const InputDecoration( decoration: const InputDecoration(
border: OutlineInputBorder(), border: OutlineInputBorder(),
hintText: 'Tell us about yourself', hintText: 'Tell us about yourself (e.g., write down what you do or what hobbies you have)',
helperText: 'Keep it short, this is just a demo.', helperText: 'Keep it short, this is just a demo.',
labelText: 'Life story', labelText: 'Life story',
), ),
......
...@@ -1719,6 +1719,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat ...@@ -1719,6 +1719,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
style: hintStyle, style: hintStyle,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
textAlign: textAlign, textAlign: textAlign,
maxLines: decoration.hintMaxLines,
), ),
); );
...@@ -1944,6 +1945,7 @@ class InputDecoration { ...@@ -1944,6 +1945,7 @@ class InputDecoration {
this.helperStyle, this.helperStyle,
this.hintText, this.hintText,
this.hintStyle, this.hintStyle,
this.hintMaxLines,
this.errorText, this.errorText,
this.errorStyle, this.errorStyle,
this.errorMaxLines, this.errorMaxLines,
...@@ -1994,6 +1996,7 @@ class InputDecoration { ...@@ -1994,6 +1996,7 @@ class InputDecoration {
labelStyle = null, labelStyle = null,
helperText = null, helperText = null,
helperStyle = null, helperStyle = null,
hintMaxLines = null,
errorText = null, errorText = null,
errorStyle = null, errorStyle = null,
errorMaxLines = null, errorMaxLines = null,
...@@ -2081,6 +2084,15 @@ class InputDecoration { ...@@ -2081,6 +2084,15 @@ class InputDecoration {
/// input field and the current [Theme]. /// input field and the current [Theme].
final TextStyle hintStyle; final TextStyle hintStyle;
/// The maximum number of lines the [hintText] can occupy.
///
/// Defaults to the value of [TextField.maxLines] attribute.
///
/// This value is passed along to the [Text.maxLines] attribute
/// of the [Text] widget used to display the hint text. [TextOverflow.ellipsis] is
/// used to handle the overflow when it is limited to single line.
final int hintMaxLines;
/// Text that appears below the input [child] and the border. /// Text that appears below the input [child] and the border.
/// ///
/// If non-null, the border's color animates to red and the [helperText] is /// If non-null, the border's color animates to red and the [helperText] is
...@@ -2449,6 +2461,7 @@ class InputDecoration { ...@@ -2449,6 +2461,7 @@ class InputDecoration {
TextStyle helperStyle, TextStyle helperStyle,
String hintText, String hintText,
TextStyle hintStyle, TextStyle hintStyle,
int hintMaxLines,
String errorText, String errorText,
TextStyle errorStyle, TextStyle errorStyle,
int errorMaxLines, int errorMaxLines,
...@@ -2484,6 +2497,7 @@ class InputDecoration { ...@@ -2484,6 +2497,7 @@ class InputDecoration {
helperStyle: helperStyle ?? this.helperStyle, helperStyle: helperStyle ?? this.helperStyle,
hintText: hintText ?? this.hintText, hintText: hintText ?? this.hintText,
hintStyle: hintStyle ?? this.hintStyle, hintStyle: hintStyle ?? this.hintStyle,
hintMaxLines: hintMaxLines ?? this.hintMaxLines,
errorText: errorText ?? this.errorText, errorText: errorText ?? this.errorText,
errorStyle: errorStyle ?? this.errorStyle, errorStyle: errorStyle ?? this.errorStyle,
errorMaxLines: errorMaxLines ?? this.errorMaxLines, errorMaxLines: errorMaxLines ?? this.errorMaxLines,
...@@ -2556,6 +2570,7 @@ class InputDecoration { ...@@ -2556,6 +2570,7 @@ class InputDecoration {
&& typedOther.helperStyle == helperStyle && typedOther.helperStyle == helperStyle
&& typedOther.hintText == hintText && typedOther.hintText == hintText
&& typedOther.hintStyle == hintStyle && typedOther.hintStyle == hintStyle
&& typedOther.hintMaxLines == hintMaxLines
&& typedOther.errorText == errorText && typedOther.errorText == errorText
&& typedOther.errorStyle == errorStyle && typedOther.errorStyle == errorStyle
&& typedOther.errorMaxLines == errorMaxLines && typedOther.errorMaxLines == errorMaxLines
...@@ -2597,6 +2612,7 @@ class InputDecoration { ...@@ -2597,6 +2612,7 @@ class InputDecoration {
helperStyle, helperStyle,
hintText, hintText,
hintStyle, hintStyle,
hintMaxLines,
errorText, errorText,
errorStyle, errorStyle,
errorMaxLines, errorMaxLines,
...@@ -2646,6 +2662,8 @@ class InputDecoration { ...@@ -2646,6 +2662,8 @@ class InputDecoration {
description.add('helperText: "$helperText"'); description.add('helperText: "$helperText"');
if (hintText != null) if (hintText != null)
description.add('hintText: "$hintText"'); description.add('hintText: "$hintText"');
if (hintMaxLines != null)
description.add('hintMaxLines: "$hintMaxLines"');
if (errorText != null) if (errorText != null)
description.add('errorText: "$errorText"'); description.add('errorText: "$errorText"');
if (errorStyle != null) if (errorStyle != null)
......
...@@ -398,6 +398,7 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi ...@@ -398,6 +398,7 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
.applyDefaults(Theme.of(context).inputDecorationTheme) .applyDefaults(Theme.of(context).inputDecorationTheme)
.copyWith( .copyWith(
enabled: widget.enabled, enabled: widget.enabled,
hintMaxLines: widget.decoration?.hintMaxLines ?? widget.maxLines
); );
if (!needsCounter) if (!needsCounter)
......
...@@ -722,6 +722,43 @@ void main() { ...@@ -722,6 +722,43 @@ void main() {
expect(inputBox.size, greaterThan(fourLineInputSize)); expect(inputBox.size, greaterThan(fourLineInputSize));
}); });
testWidgets('Multiline hint text will wrap up to maxLines', (WidgetTester tester) async {
final Key textFieldKey = UniqueKey();
Widget builder(int maxLines, final String hintMsg) {
return boilerplate(
child: TextField(
key: textFieldKey,
style: const TextStyle(color: Colors.black, fontSize: 34.0),
maxLines: maxLines,
decoration: InputDecoration(
hintText: hintMsg,
),
),
);
}
const String hintPlaceholder = 'Placeholder';
const String multipleLineText = 'Here\'s a text, which is more than one line, to demostrate the multiple line hint text';
await tester.pumpWidget(builder(null, hintPlaceholder));
RenderBox findHintText(String hint) => tester.renderObject(find.text(hint));
final RenderBox hintTextBox = findHintText(hintPlaceholder);
final Size oneLineHintSize = hintTextBox.size;
await tester.pumpWidget(builder(null, hintPlaceholder));
expect(findHintText(hintPlaceholder), equals(hintTextBox));
expect(hintTextBox.size, equals(oneLineHintSize));
const int maxLines = 3;
await tester.pumpWidget(builder(maxLines, multipleLineText));
final Text hintTextWidget = tester.widget(find.text(multipleLineText));
expect(hintTextWidget.maxLines, equals(maxLines));
expect(findHintText(multipleLineText).size, greaterThan(oneLineHintSize));
});
testWidgets('Can drag handles to change selection in multiline', (WidgetTester tester) async { testWidgets('Can drag handles to change selection in multiline', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
......
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