Revert "Fix TextField height issues (#27205)" (#29093)

This reverts commit 9e9f48dabb8423a6285bddfb21e69f0751060459.
diff --git a/packages/flutter/lib/src/material/input_decorator.dart b/packages/flutter/lib/src/material/input_decorator.dart
index 83f1e12..ca11f11 100644
--- a/packages/flutter/lib/src/material/input_decorator.dart
+++ b/packages/flutter/lib/src/material/input_decorator.dart
@@ -552,16 +552,13 @@
     @required TextDirection textDirection,
     @required TextBaseline textBaseline,
     @required bool isFocused,
-    @required bool expands,
   }) : assert(decoration != null),
        assert(textDirection != null),
        assert(textBaseline != null),
-       assert(expands != null),
        _decoration = decoration,
        _textDirection = textDirection,
        _textBaseline = textBaseline,
-       _isFocused = isFocused,
-       _expands = expands;
+       _isFocused = isFocused;
 
   final Map<_DecorationSlot, RenderBox> slotToChild = <_DecorationSlot, RenderBox>{};
   final Map<RenderBox, _DecorationSlot> childToSlot = <RenderBox, _DecorationSlot>{};
@@ -712,16 +709,6 @@
     markNeedsSemanticsUpdate();
   }
 
-  bool get expands => _expands;
-  bool _expands = false;
-  set expands(bool value) {
-    assert(value != null);
-    if (_expands == value)
-      return;
-    _expands = value;
-    markNeedsLayout();
-  }
-
   @override
   void attach(PipelineOwner owner) {
     super.attach(owner);
@@ -817,31 +804,34 @@
 
   EdgeInsets get contentPadding => decoration.contentPadding;
 
-  // Lay out the given box if needed, and return its baseline
-  double _layoutLineBox(RenderBox box, BoxConstraints constraints) {
-    if (box == null) {
-      return 0.0;
-    }
-    box.layout(constraints, parentUsesSize: true);
-    final double baseline = box.getDistanceToBaseline(textBaseline);
-    assert(baseline != null && baseline >= 0.0);
-    return baseline;
-  }
-
-  // Returns a value used by performLayout to position all of the renderers.
-  // This method applies layout to all of the renderers except the container.
-  // For convenience, the container is laid out in performLayout().
+  // Returns a value used by performLayout to position all
+  // of the renderers. This method applies layout to all of the renderers
+  // except the container. For convenience, the container is laid out
+  // in performLayout().
   _RenderDecorationLayout _layout(BoxConstraints layoutConstraints) {
-    // Margin on each side of subtext (counter and helperError)
     final Map<RenderBox, double> boxToBaseline = <RenderBox, double>{};
-    final BoxConstraints boxConstraints = layoutConstraints.loosen();
+    BoxConstraints boxConstraints = layoutConstraints.loosen();
+    double aboveBaseline = 0.0;
+    double belowBaseline = 0.0;
+    void layoutLineBox(RenderBox box) {
+      if (box == null)
+        return;
+      box.layout(boxConstraints, parentUsesSize: true);
+      final double baseline = box.getDistanceToBaseline(textBaseline);
+      assert(baseline != null && baseline >= 0.0);
+      boxToBaseline[box] = baseline;
+      aboveBaseline = math.max(baseline, aboveBaseline);
+      belowBaseline = math.max(box.size.height - baseline, belowBaseline);
+    }
+    layoutLineBox(prefix);
+    layoutLineBox(suffix);
 
-    // Layout all the widgets used by InputDecorator
-    boxToBaseline[prefix] = _layoutLineBox(prefix, boxConstraints);
-    boxToBaseline[suffix] = _layoutLineBox(suffix, boxConstraints);
-    boxToBaseline[icon] = _layoutLineBox(icon, boxConstraints);
-    boxToBaseline[prefixIcon] = _layoutLineBox(prefixIcon, boxConstraints);
-    boxToBaseline[suffixIcon] = _layoutLineBox(suffixIcon, boxConstraints);
+    if (icon != null)
+      icon.layout(boxConstraints, parentUsesSize: true);
+    if (prefixIcon != null)
+      prefixIcon.layout(boxConstraints, parentUsesSize: true);
+    if (suffixIcon != null)
+      suffixIcon.layout(boxConstraints, parentUsesSize: true);
 
     final double inputWidth = math.max(0.0, constraints.maxWidth - (
       _boxSize(icon).width
@@ -851,144 +841,72 @@
       + _boxSize(suffix).width
       + _boxSize(suffixIcon).width
       + contentPadding.right));
-    boxToBaseline[label] = _layoutLineBox(
-      label,
-      boxConstraints.copyWith(maxWidth: inputWidth),
-    );
-    boxToBaseline[hint] = _layoutLineBox(
-      hint,
-      boxConstraints.copyWith(minWidth: inputWidth, maxWidth: inputWidth),
-    );
-    boxToBaseline[counter] = _layoutLineBox(counter, boxConstraints);
 
-    // The helper or error text can occupy the full width less the space
-    // occupied by the icon and counter.
-    boxToBaseline[helperError] = _layoutLineBox(
-      helperError,
-      boxConstraints.copyWith(
+    boxConstraints = boxConstraints.copyWith(maxWidth: inputWidth);
+    if (label != null) {
+      if (decoration.alignLabelWithHint) {
+        // The label is aligned with the hint, at the baseline
+        layoutLineBox(label);
+      } else {
+        // The label is centered, not baseline aligned
+        label.layout(boxConstraints, parentUsesSize: true);
+      }
+    }
+
+    boxConstraints = boxConstraints.copyWith(minWidth: inputWidth);
+    layoutLineBox(hint);
+    layoutLineBox(input);
+
+    double inputBaseline = contentPadding.top + aboveBaseline;
+    double containerHeight = contentPadding.top
+      + aboveBaseline
+      + belowBaseline
+      + contentPadding.bottom;
+
+    if (label != null) {
+      // floatingLabelHeight includes the vertical gap between the inline
+      // elements and the floating label.
+      containerHeight += decoration.floatingLabelHeight;
+      inputBaseline += decoration.floatingLabelHeight;
+    }
+
+    containerHeight = math.max(
+      containerHeight,
+      math.max(
+        _boxSize(suffixIcon).height,
+        _boxSize(prefixIcon).height));
+
+    // Inline text within an outline border is centered within the container
+    // less 2.0 dps at the top to account for the vertical space occupied
+    // by the floating label.
+    final double outlineBaseline = aboveBaseline +
+      (containerHeight - (2.0 + aboveBaseline + belowBaseline)) / 2.0;
+
+    double subtextBaseline = 0.0;
+    double subtextHeight = 0.0;
+    if (helperError != null || counter != null) {
+      boxConstraints = layoutConstraints.loosen();
+      aboveBaseline = 0.0;
+      belowBaseline = 0.0;
+      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: math.max(0.0, boxConstraints.maxWidth
           - _boxSize(icon).width
           - _boxSize(counter).width
           - contentPadding.horizontal,
         ),
-      ),
-    );
+      );
+      layoutLineBox(helperError);
 
-    // The height of the input needs to accommodate label above and counter and
-    // helperError below, when they exist.
-    const double subtextGap = 8.0;
-    final double labelHeight = label == null
-      ? 0
-      : decoration.floatingLabelHeight;
-    final double topHeight = decoration.border.isOutline
-      ? math.max(labelHeight - boxToBaseline[label], 0)
-      : labelHeight;
-    final double counterHeight = counter == null
-      ? 0
-      : boxToBaseline[counter] + subtextGap * 2;
-    final _HelperError helperErrorWidget = decoration.helperError;
-    final double helperErrorHeight = helperErrorWidget.helperText == null
-      ? 0
-      : helperError.size.height + subtextGap * 2;
-    final double bottomHeight = math.max(
-      counterHeight,
-      helperErrorHeight,
-    );
-    boxToBaseline[input] = _layoutLineBox(
-      input,
-      boxConstraints.deflate(EdgeInsets.only(
-        top: contentPadding.top + topHeight,
-        bottom: contentPadding.bottom + bottomHeight,
-      )).copyWith(
-        minWidth: inputWidth,
-        maxWidth: inputWidth,
-      ),
-    );
-
-    // The field can be occupied by a hint or by the input itself
-    final double hintHeight = hint == null ? 0 : hint.size.height;
-    final double inputDirectHeight = input == null ? 0 : input.size.height;
-    final double inputHeight = math.max(hintHeight, inputDirectHeight);
-    final double inputInternalBaseline = math.max(
-      boxToBaseline[input],
-      boxToBaseline[hint],
-    );
-
-    // Calculate the amount that prefix/suffix affects height above and below
-    // the input.
-    final double prefixHeight = prefix == null ? 0 : prefix.size.height;
-    final double suffixHeight = suffix == null ? 0 : suffix.size.height;
-    final double fixHeight = math.max(
-      boxToBaseline[prefix],
-      boxToBaseline[suffix],
-    );
-    final double fixAboveInput = math.max(0, fixHeight - inputInternalBaseline);
-    final double fixBelowBaseline = math.max(
-      prefixHeight - boxToBaseline[prefix],
-      suffixHeight - boxToBaseline[suffix],
-    );
-    final double fixBelowInput = math.max(
-      0,
-      fixBelowBaseline - (inputHeight - inputInternalBaseline),
-    );
-
-    // Calculate the height of the input text container.
-    final double prefixIconHeight = prefixIcon == null ? 0 : prefixIcon.size.height;
-    final double suffixIconHeight = suffixIcon == null ? 0 : suffixIcon.size.height;
-    final double fixIconHeight = math.max(prefixIconHeight, suffixIconHeight);
-    final double contentHeight = math.max(
-      fixIconHeight,
-      topHeight
-      + contentPadding.top
-      + fixAboveInput
-      + inputHeight
-      + fixBelowInput
-      + contentPadding.bottom,
-    );
-    final double maxContainerHeight = boxConstraints.maxHeight - bottomHeight;
-    final double containerHeight = expands
-      ? maxContainerHeight
-      : math.min(contentHeight, maxContainerHeight);
-
-    // Always position the prefix/suffix in the same place (baseline).
-    final double overflow = math.max(0, contentHeight - maxContainerHeight);
-    final double baselineAdjustment = fixAboveInput - overflow;
-
-    // The baselines that will be used to draw the actual input text content.
-    final double inputBaseline = contentPadding.top
-      + topHeight
-      + inputInternalBaseline
-      + baselineAdjustment;
-    // The text in the input when an outline border is present is centered
-    // within the container less 2.0 dps at the top to account for the vertical
-    // space occupied by the floating label.
-    final double outlineBaseline = inputInternalBaseline
-      + baselineAdjustment / 2
-      + (containerHeight - (2.0 + inputHeight)) / 2.0;
-
-    // Find the positions of the text below the input when it exists.
-    double subtextCounterBaseline = 0;
-    double subtextHelperBaseline = 0;
-    double subtextCounterHeight = 0;
-    double subtextHelperHeight = 0;
-    if (counter != null) {
-      subtextCounterBaseline =
-        containerHeight + subtextGap + boxToBaseline[counter];
-      subtextCounterHeight = counter.size.height + subtextGap;
+      if (aboveBaseline + belowBaseline > 0.0) {
+        const double subtextGap = 8.0;
+        subtextBaseline = containerHeight + subtextGap + aboveBaseline;
+        subtextHeight = subtextGap + aboveBaseline + belowBaseline;
+      }
     }
-    if (helperErrorWidget.helperText != null) {
-      subtextHelperBaseline =
-        containerHeight + subtextGap + boxToBaseline[helperError];
-      subtextHelperHeight = helperError.size.height + subtextGap;
-    }
-    final double subtextBaseline = math.max(
-      subtextCounterBaseline,
-      subtextHelperBaseline,
-    );
-    final double subtextHeight = math.max(
-      subtextCounterHeight,
-      subtextHelperHeight,
-    );
 
     return _RenderDecorationLayout(
       boxToBaseline: boxToBaseline,
@@ -1452,18 +1370,15 @@
     @required this.textDirection,
     @required this.textBaseline,
     @required this.isFocused,
-    @required this.expands,
   }) : assert(decoration != null),
        assert(textDirection != null),
        assert(textBaseline != null),
-       assert(expands != null),
        super(key: key);
 
   final _Decoration decoration;
   final TextDirection textDirection;
   final TextBaseline textBaseline;
   final bool isFocused;
-  final bool expands;
 
   @override
   _RenderDecorationElement createElement() => _RenderDecorationElement(this);
@@ -1475,7 +1390,6 @@
       textDirection: textDirection,
       textBaseline: textBaseline,
       isFocused: isFocused,
-      expands: expands,
     );
   }
 
@@ -1485,7 +1399,6 @@
      ..decoration = decoration
      ..textDirection = textDirection
      ..textBaseline = textBaseline
-     ..expands = expands
      ..isFocused = isFocused;
   }
 }
@@ -1548,7 +1461,6 @@
     this.baseStyle,
     this.textAlign,
     this.isFocused = false,
-    this.expands = false,
     this.isEmpty = false,
     this.child,
   }) : assert(isFocused != null),
@@ -1583,19 +1495,6 @@
   /// Defaults to false.
   final bool isFocused;
 
-  /// If true, the height of the input field will be as large as possible.
-  ///
-  /// If wrapped in a widget that constrains its child's height, like Expanded
-  /// or SizedBox, the input field will only be affected if [expands] is set to
-  /// true.
-  ///
-  /// See [TextField.minLines] and [TextField.maxLines] for related ways to
-  /// affect the height of an input. When [expands] is true, both must be null
-  /// in order to avoid ambiguity in determining the height.
-  ///
-  /// Defaults to false.
-  final bool expands;
-
   /// Whether the input field is empty.
   ///
   /// Determines the position of the label text and whether to display the hint
@@ -1634,7 +1533,6 @@
     properties.add(DiagnosticsProperty<InputDecoration>('decoration', decoration));
     properties.add(DiagnosticsProperty<TextStyle>('baseStyle', baseStyle, defaultValue: null));
     properties.add(DiagnosticsProperty<bool>('isFocused', isFocused));
-    properties.add(DiagnosticsProperty<bool>('expands', expands, defaultValue: false));
     properties.add(DiagnosticsProperty<bool>('isEmpty', isEmpty));
   }
 }
@@ -2030,7 +1928,6 @@
       textDirection: textDirection,
       textBaseline: textBaseline,
       isFocused: isFocused,
-      expands: widget.expands,
     );
   }
 }
diff --git a/packages/flutter/lib/src/material/text_field.dart b/packages/flutter/lib/src/material/text_field.dart
index 6399488..9b8b141 100644
--- a/packages/flutter/lib/src/material/text_field.dart
+++ b/packages/flutter/lib/src/material/text_field.dart
@@ -147,8 +147,6 @@
     this.obscureText = false,
     this.autocorrect = true,
     this.maxLines = 1,
-    this.minLines,
-    this.expands = false,
     this.maxLength,
     this.maxLengthEnforced = true,
     this.onChanged,
@@ -173,16 +171,6 @@
        assert(scrollPadding != null),
        assert(dragStartBehavior != null),
        assert(maxLines == null || maxLines > 0),
-       assert(minLines == null || minLines > 0),
-       assert(
-         (maxLines == null) || (minLines == null) || (maxLines >= minLines),
-         'minLines can\'t be greater than maxLines',
-       ),
-       assert(expands != null),
-       assert(
-         !expands || (maxLines == null && minLines == null),
-         'minLines and maxLines must be null when expands is true.',
-       ),
        assert(maxLength == null || maxLength == TextField.noMaxLength || maxLength > 0),
        keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
        super(key: key);
@@ -281,12 +269,6 @@
   /// {@macro flutter.widgets.editableText.maxLines}
   final int maxLines;
 
-  /// {@macro flutter.widgets.editableText.minLines}
-  final int minLines;
-
-  /// {@macro flutter.widgets.editableText.expands}
-  final bool expands;
-
   /// If [maxLength] is set to this value, only the "current input length"
   /// part of the character counter is shown.
   static const int noMaxLength = -1;
@@ -475,8 +457,6 @@
     properties.add(DiagnosticsProperty<bool>('obscureText', obscureText, defaultValue: false));
     properties.add(DiagnosticsProperty<bool>('autocorrect', autocorrect, defaultValue: true));
     properties.add(IntProperty('maxLines', maxLines, defaultValue: 1));
-    properties.add(IntProperty('minLines', minLines, defaultValue: null));
-    properties.add(DiagnosticsProperty<bool>('expands', expands, defaultValue: false));
     properties.add(IntProperty('maxLength', maxLength, defaultValue: null));
     properties.add(FlagProperty('maxLengthEnforced', value: maxLengthEnforced, defaultValue: true, ifFalse: 'maxLength not enforced'));
     properties.add(EnumProperty<TextInputAction>('textInputAction', textInputAction, defaultValue: null));
@@ -871,8 +851,6 @@
         obscureText: widget.obscureText,
         autocorrect: widget.autocorrect,
         maxLines: widget.maxLines,
-        minLines: widget.minLines,
-        expands: widget.expands,
         selectionColor: themeData.textSelectionColor,
         selectionControls: widget.selectionEnabled ? textSelectionControls : null,
         onChanged: widget.onChanged,
@@ -905,7 +883,6 @@
             textAlign: widget.textAlign,
             isFocused: focusNode.hasFocus,
             isEmpty: controller.value.text.isEmpty,
-            expands: widget.expands,
             child: child,
           );
         },
diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart
index 283d734..eb4d494 100644
--- a/packages/flutter/lib/src/rendering/box.dart
+++ b/packages/flutter/lib/src/rendering/box.dart
@@ -1801,9 +1801,9 @@
         testIntrinsicsForValues(getMinIntrinsicWidth, getMaxIntrinsicWidth, 'Width', double.infinity);
         testIntrinsicsForValues(getMinIntrinsicHeight, getMaxIntrinsicHeight, 'Height', double.infinity);
         if (constraints.hasBoundedWidth)
-          testIntrinsicsForValues(getMinIntrinsicWidth, getMaxIntrinsicWidth, 'Width', constraints.maxHeight);
+          testIntrinsicsForValues(getMinIntrinsicWidth, getMaxIntrinsicWidth, 'Width', constraints.maxWidth);
         if (constraints.hasBoundedHeight)
-          testIntrinsicsForValues(getMinIntrinsicHeight, getMaxIntrinsicHeight, 'Height', constraints.maxWidth);
+          testIntrinsicsForValues(getMinIntrinsicHeight, getMaxIntrinsicHeight, 'Height', constraints.maxHeight);
 
         // TODO(ianh): Test that values are internally consistent in more ways than the above.
 
diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart
index 27b5f6b..adbbc63 100644
--- a/packages/flutter/lib/src/rendering/editable.dart
+++ b/packages/flutter/lib/src/rendering/editable.dart
@@ -144,8 +144,6 @@
     ValueNotifier<bool> showCursor,
     bool hasFocus,
     int maxLines = 1,
-    int minLines,
-    bool expands = false,
     StrutStyle strutStyle,
     Color selectionColor,
     double textScaleFactor = 1.0,
@@ -167,16 +165,6 @@
   }) : assert(textAlign != null),
        assert(textDirection != null, 'RenderEditable created without a textDirection.'),
        assert(maxLines == null || maxLines > 0),
-       assert(minLines == null || minLines > 0),
-       assert(
-         (maxLines == null) || (minLines == null) || (maxLines >= minLines),
-         'minLines can\'t be greater than maxLines',
-       ),
-       assert(expands != null),
-       assert(
-         !expands || (maxLines == null && minLines == null),
-         'minLines and maxLines must be null when expands is true.',
-       ),
        assert(textScaleFactor != null),
        assert(offset != null),
        assert(ignorePointer != null),
@@ -198,8 +186,6 @@
        _showCursor = showCursor ?? ValueNotifier<bool>(false),
        _hasFocus = hasFocus ?? false,
        _maxLines = maxLines,
-       _minLines = minLines,
-       _expands = expands,
        _selectionColor = selectionColor,
        _selection = selection,
        _offset = offset,
@@ -705,29 +691,6 @@
     markNeedsTextLayout();
   }
 
-  /// {@macro flutter.widgets.editableText.minLines}
-  int get minLines => _minLines;
-  int _minLines;
-  /// The value may be null. If it is not null, then it must be greater than zero.
-  set minLines(int value) {
-    assert(value == null || value > 0);
-    if (minLines == value)
-      return;
-    _minLines = value;
-    markNeedsTextLayout();
-  }
-
-  /// {@macro flutter.widgets.editableText.expands}
-  bool get expands => _expands;
-  bool _expands;
-  set expands(bool value) {
-    assert(value != null);
-    if (expands == value)
-      return;
-    _expands = value;
-    markNeedsTextLayout();
-  }
-
   /// The color to use when painting the selection.
   Color get selectionColor => _selectionColor;
   Color _selectionColor;
@@ -1187,28 +1150,8 @@
   double get preferredLineHeight => _textPainter.preferredLineHeight;
 
   double _preferredHeight(double width) {
-    // Lock height to maxLines if needed
-    final bool lockedMax = maxLines != null && minLines == null;
-    final bool lockedBoth = minLines != null && minLines == maxLines;
-    final bool singleLine = maxLines == 1;
-    if (singleLine || lockedMax || lockedBoth) {
+    if (maxLines != null)
       return preferredLineHeight * maxLines;
-    }
-
-    // Clamp height to minLines or maxLines if needed
-    final bool minLimited = minLines != null && minLines > 1;
-    final bool maxLimited = maxLines != null;
-    if (minLimited || maxLimited) {
-      _layoutText(width);
-      if (minLimited && _textPainter.height < preferredLineHeight * minLines) {
-        return preferredLineHeight * minLines;
-      }
-      if (maxLimited && _textPainter.height > preferredLineHeight * maxLines) {
-        return preferredLineHeight * maxLines;
-      }
-    }
-
-    // Set the height based on the content
     if (width == double.infinity) {
       final String text = _textPainter.text.toPlainText();
       int lines = 1;
@@ -1670,8 +1613,6 @@
     properties.add(DiagnosticsProperty<Color>('cursorColor', cursorColor));
     properties.add(DiagnosticsProperty<ValueNotifier<bool>>('showCursor', showCursor));
     properties.add(IntProperty('maxLines', maxLines));
-    properties.add(IntProperty('minLines', minLines));
-    properties.add(DiagnosticsProperty<bool>('expands', expands, defaultValue: false));
     properties.add(DiagnosticsProperty<Color>('selectionColor', selectionColor));
     properties.add(DoubleProperty('textScaleFactor', textScaleFactor));
     properties.add(DiagnosticsProperty<Locale>('locale', locale, defaultValue: null));
diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart
index d6a0b04..1012034 100644
--- a/packages/flutter/lib/src/widgets/editable_text.dart
+++ b/packages/flutter/lib/src/widgets/editable_text.dart
@@ -278,8 +278,6 @@
     this.locale,
     this.textScaleFactor,
     this.maxLines = 1,
-    this.minLines,
-    this.expands = false,
     this.autofocus = false,
     this.selectionColor,
     this.selectionControls,
@@ -312,16 +310,6 @@
        assert(backgroundCursorColor != null),
        assert(textAlign != null),
        assert(maxLines == null || maxLines > 0),
-       assert(minLines == null || minLines > 0),
-       assert(
-         (maxLines == null) || (minLines == null) || (maxLines >= minLines),
-         'minLines can\'t be greater than maxLines',
-       ),
-       assert(expands != null),
-       assert(
-         !expands || (maxLines == null && minLines == null),
-         'minLines and maxLines must be null when expands is true.',
-       ),
        assert(autofocus != null),
        assert(rendererIgnoresPointer != null),
        assert(scrollPadding != null),
@@ -477,78 +465,12 @@
   /// container will start with enough vertical space for one line and
   /// automatically grow to accommodate additional lines as they are entered.
   ///
-  /// If this is not null, the value must be greater than zero, and it will lock
-  /// the input to the given number of lines and take up enough horizontal space
-  /// to accommodate that number of lines. Setting [minLines] as well allows the
-  /// input to grow between the indicated range.
-  ///
-  /// The full set of behaviors possible with [minLines] and [maxLines] are as
-  /// follows. These examples apply equally to `TextField`, `TextFormField`, and
-  /// `EditableText`.
-  ///
-  /// Input that occupies a single line and scrolls horizontally as needed.
-  /// ```dart
-  /// TextField()
-  /// ```
-  ///
-  /// Input whose height grows from one line up to as many lines as needed for
-  /// the text that was entered. If a height limit is imposed by its parent, it
-  /// will scroll vertically when its height reaches that limit.
-  /// ```dart
-  /// TextField(maxLines: null)
-  /// ```
-  ///
-  /// The input's height is large enough for the given number of lines. If
-  /// additional lines are entered the input scrolls vertically.
-  /// ```dart
-  /// TextField(maxLines: 2)
-  /// ```
-  ///
-  /// Input whose height grows with content between a min and max. An infinite
-  /// max is possible with `maxLines: null`.
-  /// ```dart
-  /// TextField(minLines: 2, maxLines: 4)
-  /// ```
+  /// If it is not null, the value must be greater than zero. If it is greater
+  /// than 1, it will take up enough horizontal space to accommodate that number
+  /// of lines.
   /// {@endtemplate}
   final int maxLines;
 
-  /// {@template flutter.widgets.editableText.minLines}
-  /// The minimum number of lines to occupy when the content spans fewer lines.
-
-  /// When [maxLines] is set as well, the height will grow between the indicated
-  /// range of lines. When [maxLines] is null, it will grow as high as needed,
-  /// starting from [minLines].
-  ///
-  /// See the examples in [maxLines] for the complete picture of how [maxLines]
-  /// and [minLines] interact to produce various behaviors.
-  ///
-  /// Defaults to null.
-  /// {@endtemplate}
-  final int minLines;
-
-  /// {@template flutter.widgets.editableText.expands}
-  /// Whether this widget's height will be sized to fill its parent.
-  ///
-  /// If set to true and wrapped in a parent widget like [Expanded] or
-  /// [SizedBox], the input will expand to fill the parent.
-  ///
-  /// [maxLines] and [minLines] must both be null when this is set to true,
-  /// otherwise an error is thrown.
-  ///
-  /// Defaults to false.
-  ///
-  /// See the examples in [maxLines] for the complete picture of how [maxLines],
-  /// [minLines], and [expands] interact to produce various behaviors.
-  ///
-  /// Input that matches the height of its parent
-  /// ```dart
-  /// Expanded(
-  ///   child: TextField(maxLines: null, expands: true),
-  /// )
-  /// ```
-  /// {@endtemplate}
-  final bool expands;
-
   /// {@template flutter.widgets.editableText.autofocus}
   /// Whether this text field should focus itself if nothing else is already
   /// focused.
@@ -754,8 +676,6 @@
     properties.add(DiagnosticsProperty<Locale>('locale', locale, defaultValue: null));
     properties.add(DoubleProperty('textScaleFactor', textScaleFactor, defaultValue: null));
     properties.add(IntProperty('maxLines', maxLines, defaultValue: 1));
-    properties.add(IntProperty('minLines', minLines, defaultValue: null));
-    properties.add(DiagnosticsProperty<bool>('expands', expands, defaultValue: false));
     properties.add(DiagnosticsProperty<bool>('autofocus', autofocus, defaultValue: false));
     properties.add(DiagnosticsProperty<TextInputType>('keyboardType', keyboardType, defaultValue: null));
   }
@@ -875,7 +795,7 @@
         // If this is a multiline EditableText, do nothing for a "newline"
         // action; The newline is already inserted. Otherwise, finalize
         // editing.
-        if (!_isMultiline)
+        if (widget.maxLines == 1)
           _finalizeEditing(true);
         break;
       case TextInputAction.done:
@@ -1413,8 +1333,6 @@
                   : _cursorVisibilityNotifier,
               hasFocus: _hasFocus,
               maxLines: widget.maxLines,
-              minLines: widget.minLines,
-              expands: widget.expands,
               strutStyle: widget.strutStyle,
               selectionColor: widget.selectionColor,
               textScaleFactor: widget.textScaleFactor ?? MediaQuery.textScaleFactorOf(context),
@@ -1485,8 +1403,6 @@
     this.showCursor,
     this.hasFocus,
     this.maxLines,
-    this.minLines,
-    this.expands,
     this.strutStyle,
     this.selectionColor,
     this.textScaleFactor,
@@ -1517,8 +1433,6 @@
   final ValueNotifier<bool> showCursor;
   final bool hasFocus;
   final int maxLines;
-  final int minLines;
-  final bool expands;
   final StrutStyle strutStyle;
   final Color selectionColor;
   final double textScaleFactor;
@@ -1548,8 +1462,6 @@
       showCursor: showCursor,
       hasFocus: hasFocus,
       maxLines: maxLines,
-      minLines: minLines,
-      expands: expands,
       strutStyle: strutStyle,
       selectionColor: selectionColor,
       textScaleFactor: textScaleFactor,
@@ -1580,8 +1492,6 @@
       ..showCursor = showCursor
       ..hasFocus = hasFocus
       ..maxLines = maxLines
-      ..minLines = minLines
-      ..expands = expands
       ..strutStyle = strutStyle
       ..selectionColor = selectionColor
       ..textScaleFactor = textScaleFactor
diff --git a/packages/flutter/test/material/input_decorator_test.dart b/packages/flutter/test/material/input_decorator_test.dart
index 8e8cba8..101a1eb 100644
--- a/packages/flutter/test/material/input_decorator_test.dart
+++ b/packages/flutter/test/material/input_decorator_test.dart
@@ -993,100 +993,6 @@
     expect(tester.getTopRight(find.text('text')).dx, lessThanOrEqualTo(tester.getTopRight(find.byKey(sKey)).dx));
   });
 
-  testWidgets('InputDecorator tall prefix', (WidgetTester tester) async {
-    const Key pKey = Key('p');
-    await tester.pumpWidget(
-      buildInputDecorator(
-        // isEmpty: false (default)
-        // isFocused: false (default)
-        decoration: InputDecoration(
-          prefix: Container(
-            key: pKey,
-            height: 100,
-            width: 10,
-          ),
-          filled: true,
-        ),
-        // Set the fontSize so that everything works out to whole numbers.
-        child: const Text(
-          'text',
-          style: TextStyle(fontFamily: 'Ahem', fontSize: 20.0),
-        ),
-      ),
-    );
-
-    // Overall height for this InputDecorator is ~127.2dps because
-    // the prefix is 100dps tall, but it aligns with the input's baseline,
-    // overlapping the input a bit.
-    //   12 - top padding
-    //  100 - total height of prefix
-    //  -16 - input prefix overlap (distance input top to baseline, not exact)
-    //   20 - input text (ahem font size 16dps)
-    //    0 - bottom prefix/suffix padding
-    //   12 - bottom padding
-
-    expect(tester.getSize(find.byType(InputDecorator)).width, 800.0);
-    expect(tester.getSize(find.byType(InputDecorator)).height, closeTo(128.0, .0001));
-    expect(tester.getSize(find.text('text')).height, 20.0);
-    expect(tester.getSize(find.byKey(pKey)).height, 100.0);
-    expect(tester.getTopLeft(find.text('text')).dy, closeTo(96, .0001)); // 12 + 100 - 16
-    expect(tester.getTopLeft(find.byKey(pKey)).dy, 12.0);
-
-    // layout is a row: [prefix text suffix]
-    expect(tester.getTopLeft(find.byKey(pKey)).dx, 12.0);
-    expect(tester.getTopRight(find.byKey(pKey)).dx, tester.getTopLeft(find.text('text')).dx);
-  });
-
-  testWidgets('InputDecorator tall prefix with border', (WidgetTester tester) async {
-    const Key pKey = Key('p');
-    await tester.pumpWidget(
-      buildInputDecorator(
-        // isEmpty: false (default)
-        // isFocused: false (default)
-        decoration: InputDecoration(
-          border: const OutlineInputBorder(),
-          prefix: Container(
-            key: pKey,
-            height: 100,
-            width: 10,
-          ),
-          filled: true,
-        ),
-        // Set the fontSize so that everything works out to whole numbers.
-        child: const Text(
-          'text',
-          style: TextStyle(fontFamily: 'Ahem', fontSize: 20.0),
-        ),
-      ),
-    );
-
-    // Overall height for this InputDecorator is ~127.2dps because
-    // the prefix is 100dps tall, but it aligns with the input's baseline,
-    // overlapping the input a bit.
-    //   24 - top padding
-    //  100 - total height of prefix
-    //  -16 - input prefix overlap (distance input top to baseline, not exact)
-    //   20 - input text (ahem font size 16dps)
-    //    0 - bottom prefix/suffix padding
-    //   16 - bottom padding
-    // When a border is present, the input text and prefix/suffix are centered
-    // within the input. Here, that will be content of height 106, including 2
-    // extra pixels of space, centered within an input of height 144. That gives
-    // 19 pixels of space on each side of the content, so the prefix is
-    // positioned at 19, and the text is at 19+100-16=103.
-
-    expect(tester.getSize(find.byType(InputDecorator)).width, 800.0);
-    expect(tester.getSize(find.byType(InputDecorator)).height, closeTo(144, .0001));
-    expect(tester.getSize(find.text('text')).height, 20.0);
-    expect(tester.getSize(find.byKey(pKey)).height, 100.0);
-    expect(tester.getTopLeft(find.text('text')).dy, closeTo(103, .0001));
-    expect(tester.getTopLeft(find.byKey(pKey)).dy, 19.0);
-
-    // layout is a row: [prefix text suffix]
-    expect(tester.getTopLeft(find.byKey(pKey)).dx, 12.0);
-    expect(tester.getTopRight(find.byKey(pKey)).dx, tester.getTopLeft(find.text('text')).dx);
-  });
-
   testWidgets('InputDecorator prefixIcon/suffixIcon', (WidgetTester tester) async {
     await tester.pumpWidget(
       buildInputDecorator(
@@ -1169,6 +1075,7 @@
     expect(tester.getTopLeft(find.byKey(prefixKey)).dy, 0.0);
   });
 
+
   testWidgets('counter text has correct right margin - LTR, not dense', (WidgetTester tester) async {
     await tester.pumpWidget(
       buildInputDecorator(
@@ -1556,12 +1463,12 @@
   testWidgets('InputDecoration outline shape with no border and no floating placeholder', (WidgetTester tester) async {
     await tester.pumpWidget(
       buildInputDecorator(
-        // isFocused: false (default)
-        isEmpty: true,
-        decoration: const InputDecoration(
-          border: OutlineInputBorder(borderSide: BorderSide.none),
-          hasFloatingPlaceholder: false,
-          labelText: 'label',
+      // isFocused: false (default)
+      isEmpty: true,
+      decoration: const InputDecoration(
+        border: OutlineInputBorder(borderSide: BorderSide.none),
+        hasFloatingPlaceholder: false,
+        labelText: 'label',
         ),
       ),
     );
diff --git a/packages/flutter/test/material/text_field_focus_test.dart b/packages/flutter/test/material/text_field_focus_test.dart
index f7044ee..67039ea 100644
--- a/packages/flutter/test/material/text_field_focus_test.dart
+++ b/packages/flutter/test/material/text_field_focus_test.dart
@@ -6,49 +6,6 @@
 import 'package:flutter/material.dart';
 
 void main() {
-  testWidgets('Dialog interaction', (WidgetTester tester) async {
-    expect(tester.testTextInput.isVisible, isFalse);
-
-    await tester.pumpWidget(
-      const MaterialApp(
-        home: Material(
-          child: Center(
-            child: TextField(
-              autofocus: true,
-            ),
-          ),
-        ),
-      ),
-    );
-
-    expect(tester.testTextInput.isVisible, isTrue);
-
-    final BuildContext context = tester.element(find.byType(TextField));
-
-    showDialog<void>(
-      context: context,
-      builder: (BuildContext context) => const SimpleDialog(title: Text('Dialog')),
-    );
-
-    await tester.pump();
-
-    expect(tester.testTextInput.isVisible, isFalse);
-
-    Navigator.of(tester.element(find.text('Dialog'))).pop();
-    await tester.pump();
-
-    expect(tester.testTextInput.isVisible, isFalse);
-
-    await tester.tap(find.byType(TextField));
-    await tester.idle();
-
-    expect(tester.testTextInput.isVisible, isTrue);
-
-    await tester.pumpWidget(Container());
-
-    expect(tester.testTextInput.isVisible, isFalse);
-  });
-
   testWidgets('Request focus shows keyboard', (WidgetTester tester) async {
     final FocusNode focusNode = FocusNode();
 
@@ -132,6 +89,49 @@
     expect(tester.testTextInput.isVisible, isFalse);
   });
 
+  testWidgets('Dialog interaction', (WidgetTester tester) async {
+    expect(tester.testTextInput.isVisible, isFalse);
+
+    await tester.pumpWidget(
+      const MaterialApp(
+        home: Material(
+          child: Center(
+            child: TextField(
+              autofocus: true,
+            ),
+          ),
+        ),
+      ),
+    );
+
+    expect(tester.testTextInput.isVisible, isTrue);
+
+    final BuildContext context = tester.element(find.byType(TextField));
+
+    showDialog<void>(
+      context: context,
+      builder: (BuildContext context) => const SimpleDialog(title: Text('Dialog')),
+    );
+
+    await tester.pump();
+
+    expect(tester.testTextInput.isVisible, isFalse);
+
+    Navigator.of(tester.element(find.text('Dialog'))).pop();
+    await tester.pump();
+
+    expect(tester.testTextInput.isVisible, isFalse);
+
+    await tester.tap(find.byType(TextField));
+    await tester.idle();
+
+    expect(tester.testTextInput.isVisible, isTrue);
+
+    await tester.pumpWidget(Container());
+
+    expect(tester.testTextInput.isVisible, isFalse);
+  });
+
   testWidgets('Focus triggers keep-alive', (WidgetTester tester) async {
     final FocusNode focusNode = FocusNode();
 
diff --git a/packages/flutter/test/material/text_field_test.dart b/packages/flutter/test/material/text_field_test.dart
index 20dadfc..7cd6d3b 100644
--- a/packages/flutter/test/material/text_field_test.dart
+++ b/packages/flutter/test/material/text_field_test.dart
@@ -174,24 +174,6 @@
     debugResetSemanticsIdCounter();
   });
 
-  final Key textFieldKey = UniqueKey();
-  Widget textFieldBuilder({
-    int maxLines = 1,
-    int minLines,
-  }) {
-    return boilerplate(
-      child: TextField(
-        key: textFieldKey,
-        style: const TextStyle(color: Colors.black, fontSize: 34.0),
-        maxLines: maxLines,
-        minLines: minLines,
-        decoration: const InputDecoration(
-          hintText: 'Placeholder',
-        ),
-      ),
-    );
-  }
-
   testWidgets('TextField passes onEditingComplete to EditableText', (WidgetTester tester) async {
     final VoidCallback onEditingComplete = () { };
 
@@ -901,288 +883,71 @@
     expect(controller.selection.isCollapsed, false);
   });
 
-  testWidgets('TextField height with minLines unset', (WidgetTester tester) async {
-    await tester.pumpWidget(textFieldBuilder());
+  testWidgets('Multiline text will wrap up to maxLines', (WidgetTester tester) async {
+    final Key textFieldKey = UniqueKey();
 
-    RenderBox findInputBox() => tester.renderObject(find.byKey(textFieldKey));
-
-    final RenderBox inputBox = findInputBox();
-    final Size emptyInputSize = inputBox.size;
-
-    await tester.enterText(find.byType(TextField), 'No wrapping here.');
-    await tester.pumpWidget(textFieldBuilder());
-    expect(findInputBox(), equals(inputBox));
-    expect(inputBox.size, equals(emptyInputSize));
-
-    // Even when entering multiline text, TextField doesn't grow. It's a single
-    // line input.
-    await tester.enterText(find.byType(TextField), kThreeLines);
-    await tester.pumpWidget(textFieldBuilder());
-    expect(findInputBox(), equals(inputBox));
-    expect(inputBox.size, equals(emptyInputSize));
-
-    // maxLines: 3 makes the TextField 3 lines tall
-    await tester.enterText(find.byType(TextField), '');
-    await tester.pumpWidget(textFieldBuilder(maxLines: 3));
-    expect(findInputBox(), equals(inputBox));
-    expect(inputBox.size.height, greaterThan(emptyInputSize.height));
-    expect(inputBox.size.width, emptyInputSize.width);
-
-    final Size threeLineInputSize = inputBox.size;
-
-    // Filling with 3 lines of text stays the same size
-    await tester.enterText(find.byType(TextField), kThreeLines);
-    await tester.pumpWidget(textFieldBuilder(maxLines: 3));
-    expect(findInputBox(), equals(inputBox));
-    expect(inputBox.size, threeLineInputSize);
-
-    // An extra line won't increase the size because we max at 3.
-    await tester.enterText(find.byType(TextField), kMoreThanFourLines);
-    await tester.pumpWidget(textFieldBuilder(maxLines: 3));
-    expect(findInputBox(), equals(inputBox));
-    expect(inputBox.size, threeLineInputSize);
-
-    // But now it will... but it will max at four
-    await tester.enterText(find.byType(TextField), kMoreThanFourLines);
-    await tester.pumpWidget(textFieldBuilder(maxLines: 4));
-    expect(findInputBox(), equals(inputBox));
-    expect(inputBox.size.height, greaterThan(threeLineInputSize.height));
-    expect(inputBox.size.width, threeLineInputSize.width);
-
-    final Size fourLineInputSize = inputBox.size;
-
-    // Now it won't max out until the end
-    await tester.enterText(find.byType(TextField), '');
-    await tester.pumpWidget(textFieldBuilder(maxLines: null));
-    expect(findInputBox(), equals(inputBox));
-    expect(inputBox.size, equals(emptyInputSize));
-    await tester.enterText(find.byType(TextField), kThreeLines);
-    await tester.pump();
-    expect(inputBox.size, equals(threeLineInputSize));
-    await tester.enterText(find.byType(TextField), kMoreThanFourLines);
-    await tester.pump();
-    expect(inputBox.size.height, greaterThan(fourLineInputSize.height));
-    expect(inputBox.size.width, fourLineInputSize.width);
-  });
-
-  testWidgets('TextField height with minLines and maxLines', (WidgetTester tester) async {
-    await tester.pumpWidget(textFieldBuilder());
-
-    RenderBox findInputBox() => tester.renderObject(find.byKey(textFieldKey));
-
-    final RenderBox inputBox = findInputBox();
-    final Size emptyInputSize = inputBox.size;
-
-    await tester.enterText(find.byType(TextField), 'No wrapping here.');
-    await tester.pumpWidget(textFieldBuilder());
-    expect(findInputBox(), equals(inputBox));
-    expect(inputBox.size, equals(emptyInputSize));
-
-    // min and max set to same value locks height to value.
-    await tester.pumpWidget(textFieldBuilder(minLines: 3, maxLines: 3));
-    expect(findInputBox(), equals(inputBox));
-    expect(inputBox.size.height, greaterThan(emptyInputSize.height));
-    expect(inputBox.size.width, emptyInputSize.width);
-
-    final Size threeLineInputSize = inputBox.size;
-
-    // maxLines: null with minLines set grows beyond minLines
-    await tester.pumpWidget(textFieldBuilder(minLines: 3, maxLines: null));
-    expect(findInputBox(), equals(inputBox));
-    expect(inputBox.size, threeLineInputSize);
-    await tester.enterText(find.byType(TextField), kMoreThanFourLines);
-    await tester.pump();
-    expect(inputBox.size.height, greaterThan(threeLineInputSize.height));
-    expect(inputBox.size.width, threeLineInputSize.width);
-
-    // With minLines and maxLines set, input will expand through the range
-    await tester.enterText(find.byType(TextField), '');
-    await tester.pumpWidget(textFieldBuilder(minLines: 3, maxLines: 4));
-    expect(findInputBox(), equals(inputBox));
-    expect(inputBox.size, equals(threeLineInputSize));
-    await tester.enterText(find.byType(TextField), kMoreThanFourLines);
-    await tester.pump();
-    expect(inputBox.size.height, greaterThan(threeLineInputSize.height));
-    expect(inputBox.size.width, threeLineInputSize.width);
-
-    // minLines can't be greater than maxLines.
-    expect(() async {
-      await tester.pumpWidget(textFieldBuilder(minLines: 3, maxLines: 2));
-    }, throwsAssertionError);
-    expect(() async {
-      await tester.pumpWidget(textFieldBuilder(minLines: 3));
-    }, throwsAssertionError);
-
-    // maxLines defaults to 1 and can't be less than minLines
-    expect(() async {
-      await tester.pumpWidget(textFieldBuilder(minLines: 3));
-    }, throwsAssertionError);
-  });
-
-  testWidgets('Multiline text when wrapped in Expanded', (WidgetTester tester) async {
-    Widget expandedTextFieldBuilder({
-      int maxLines = 1,
-      int minLines,
-      bool expands = false,
-    }) {
+    Widget builder(int maxLines) {
       return boilerplate(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: <Widget>[
-            Expanded(
-              child: TextField(
-                key: textFieldKey,
-                style: const TextStyle(color: Colors.black, fontSize: 34.0),
-                maxLines: maxLines,
-                minLines: minLines,
-                expands: expands,
-                decoration: const InputDecoration(
-                  hintText: 'Placeholder',
-                ),
-              ),
-            ),
-          ],
-        ),
-      );
-    }
-
-    await tester.pumpWidget(expandedTextFieldBuilder());
-
-    RenderBox findBorder() {
-      return tester.renderObject(find.descendant(
-        of: find.byType(InputDecorator),
-        matching: find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_BorderContainer'),
-      ));
-    }
-    final RenderBox border = findBorder();
-
-    // Without expanded: true and maxLines: null, the TextField does not expand
-    // to fill its parent when wrapped in an Expanded widget.
-    final Size unexpandedInputSize = border.size;
-
-    // It does expand to fill its parent when expands: true, maxLines: null, and
-    // it's wrapped in an Expanded widget.
-    await tester.pumpWidget(expandedTextFieldBuilder(expands: true, maxLines: null));
-    expect(border.size.height, greaterThan(unexpandedInputSize.height));
-    expect(border.size.width, unexpandedInputSize.width);
-
-    // min/maxLines that is not null and expands: true contradict each other.
-    expect(() async {
-      await tester.pumpWidget(expandedTextFieldBuilder(expands: true, maxLines: 4));
-    }, throwsAssertionError);
-    expect(() async {
-      await tester.pumpWidget(expandedTextFieldBuilder(expands: true, minLines: 1, maxLines: null));
-    }, throwsAssertionError);
-  });
-
-  testWidgets('Growable TextField when content height exceeds parent', (WidgetTester tester) async {
-    const double height = 200.0;
-    const double padding = 24.0;
-
-    Widget containedTextFieldBuilder({
-      Widget counter,
-      String helperText,
-      String labelText,
-      Widget prefix,
-    }) {
-      return boilerplate(
-        child: Container(
-          height: height,
-          child: TextField(
-            key: textFieldKey,
-            maxLines: null,
-            decoration: InputDecoration(
-              counter: counter,
-              helperText: helperText,
-              labelText: labelText,
-              prefix: prefix,
-            ),
+        child: TextField(
+          key: textFieldKey,
+          style: const TextStyle(color: Colors.black, fontSize: 34.0),
+          maxLines: maxLines,
+          decoration: const InputDecoration(
+            hintText: 'Placeholder',
           ),
         ),
       );
     }
 
-    await tester.pumpWidget(containedTextFieldBuilder());
-    RenderBox findEditableText() => tester.renderObject(find.byType(EditableText));
+    await tester.pumpWidget(builder(null));
 
-    final RenderBox inputBox = findEditableText();
+    RenderBox findInputBox() => tester.renderObject(find.byKey(textFieldKey));
 
-    // With no decoration and when overflowing with content, the EditableText
-    // takes up the full height minus the padding, so the input fits perfectly
-    // inside the parent.
-    await tester.enterText(find.byType(TextField), 'a\n' * 11);
-    await tester.pump();
-    expect(findEditableText(), equals(inputBox));
-    expect(inputBox.size.height, height - padding);
+    final RenderBox inputBox = findInputBox();
+    final Size emptyInputSize = inputBox.size;
 
-    // Adding a counter causes the EditableText to shrink to fit the counter
-    // inside the parent as well.
-    const double counterHeight = 40.0;
-    const double subtextGap = 8.0 * 2;
-    const double counterSpace = counterHeight + subtextGap;
-    await tester.pumpWidget(containedTextFieldBuilder(
-      counter: Container(height: counterHeight),
-    ));
-    expect(findEditableText(), equals(inputBox));
-    expect(inputBox.size.height, height - padding - counterSpace);
+    await tester.enterText(find.byType(TextField), 'No wrapping here.');
+    await tester.pumpWidget(builder(null));
+    expect(findInputBox(), equals(inputBox));
+    expect(inputBox.size, equals(emptyInputSize));
 
-    // Including helperText causes the EditableText to shrink to fit the text
-    // inside the parent as well.
-    await tester.pumpWidget(containedTextFieldBuilder(
-      helperText: 'I am helperText',
-    ));
-    expect(findEditableText(), equals(inputBox));
-    const double helperTextSpace = 28.0;
-    expect(inputBox.size.height, height - padding - helperTextSpace);
+    await tester.pumpWidget(builder(3));
+    expect(findInputBox(), equals(inputBox));
+    expect(inputBox.size, greaterThan(emptyInputSize));
 
-    // When both helperText and counter are present, EditableText shrinks by the
-    // height of the taller of the two in order to fit both within the parent.
-    await tester.pumpWidget(containedTextFieldBuilder(
-      counter: Container(height: counterHeight),
-      helperText: 'I am helperText',
-    ));
-    expect(findEditableText(), equals(inputBox));
-    expect(inputBox.size.height, height - padding - counterSpace);
+    final Size threeLineInputSize = inputBox.size;
 
-    // When a label is present, EditableText shrinks to fit it at the top so
-    // that the bottom of the input still lines up perfectly with the parent.
-    await tester.pumpWidget(containedTextFieldBuilder(
-      labelText: 'I am labelText',
-    ));
-    const double labelSpace = 16.0;
-    expect(findEditableText(), equals(inputBox));
-    expect(inputBox.size.height, height - padding - labelSpace);
+    await tester.enterText(find.byType(TextField), kThreeLines);
+    await tester.pumpWidget(builder(null));
+    expect(findInputBox(), equals(inputBox));
+    expect(inputBox.size, greaterThan(emptyInputSize));
 
-    // When decoration is present on the top and bottom, EditableText shrinks to
-    // fit both inside the parent independently.
-    await tester.pumpWidget(containedTextFieldBuilder(
-      counter: Container(height: counterHeight),
-      labelText: 'I am labelText',
-    ));
-    expect(findEditableText(), equals(inputBox));
-    expect(inputBox.size.height, height - padding - counterSpace - labelSpace);
+    await tester.enterText(find.byType(TextField), kThreeLines);
+    await tester.pumpWidget(builder(null));
+    expect(findInputBox(), equals(inputBox));
+    expect(inputBox.size, threeLineInputSize);
 
-    // When a prefix or suffix is present in an input that's full of content,
-    // it is ignored and allowed to expand beyond the top of the input. Other
-    // top and bottom decoration is still respected.
-    await tester.pumpWidget(containedTextFieldBuilder(
-      counter: Container(height: counterHeight),
-      labelText: 'I am labelText',
-      prefix: Container(
-        width: 10,
-        height: 60,
-      ),
-    ));
-    expect(findEditableText(), equals(inputBox));
-    expect(
-      inputBox.size.height,
-      height
-      - padding
-      - labelSpace
-      - counterSpace,
-    );
+    // An extra line won't increase the size because we max at 3.
+    await tester.enterText(find.byType(TextField), kMoreThanFourLines);
+    await tester.pumpWidget(builder(3));
+    expect(findInputBox(), equals(inputBox));
+    expect(inputBox.size, threeLineInputSize);
+
+    // But now it will... but it will max at four
+    await tester.enterText(find.byType(TextField), kMoreThanFourLines);
+    await tester.pumpWidget(builder(4));
+    expect(findInputBox(), equals(inputBox));
+    expect(inputBox.size, greaterThan(threeLineInputSize));
+
+    final Size fourLineInputSize = inputBox.size;
+
+    // Now it won't max out until the end
+    await tester.pumpWidget(builder(null));
+    expect(findInputBox(), equals(inputBox));
+    expect(inputBox.size, greaterThan(fourLineInputSize));
   });
 
+
   testWidgets('Multiline hint text will wrap up to maxLines', (WidgetTester tester) async {
     final Key textFieldKey = UniqueKey();
 
diff --git a/packages/flutter/test/rendering/editable_test.dart b/packages/flutter/test/rendering/editable_test.dart
index f54ba7a..196eb31 100644
--- a/packages/flutter/test/rendering/editable_test.dart
+++ b/packages/flutter/test/rendering/editable_test.dart
@@ -56,7 +56,6 @@
         ' │ cursorColor: null\n'
         ' │ showCursor: ValueNotifier<bool>#00000(false)\n'
         ' │ maxLines: 1\n'
-        ' │ minLines: null\n'
         ' │ selectionColor: null\n'
         ' │ textScaleFactor: 1.0\n'
         ' │ locale: ja_JP\n'