Skip to content

Commit

Permalink
Revert "Revert "Fix computeMinIntrinsicHeight in _RenderDecoration (f…
Browse files Browse the repository at this point in the history
…lutter#87404)" (flutter#89667)" (flutter#89822)

Improve the layout/sizing of InputDecorator
  • Loading branch information
smitsk committed Sep 16, 2021
1 parent f10f3e7 commit 93de90b
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 14 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,4 @@ Mirko Mucaria <skogsfrae@gmail.com>
Karol Czeryna <karol.czeryna@gmail.com>
Callum Moffat <callum@moffatman.com>
Koutaro Mori <koutaro.mo@gmail.com>
Sergei Smitskoi <sergflutterdev@gmail.com>
60 changes: 46 additions & 14 deletions packages/flutter/lib/src/material/input_decorator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -971,11 +971,17 @@ class _RenderDecoration extends RenderBox {
final BoxConstraints boxConstraints = layoutConstraints.loosen();

// 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);
final BoxConstraints containerConstraints = boxConstraints.copyWith(
maxWidth: boxConstraints.maxWidth - _boxSize(icon).width,
);
boxToBaseline[prefixIcon] = _layoutLineBox(prefixIcon, containerConstraints);
boxToBaseline[suffixIcon] = _layoutLineBox(suffixIcon, containerConstraints);
final BoxConstraints contentConstraints = containerConstraints.copyWith(
maxWidth: containerConstraints.maxWidth - contentPadding.horizontal,
);
boxToBaseline[prefix] = _layoutLineBox(prefix, contentConstraints);
boxToBaseline[suffix] = _layoutLineBox(suffix, contentConstraints);

final double inputWidth = math.max(
0.0,
Expand Down Expand Up @@ -1011,18 +1017,14 @@ class _RenderDecoration extends RenderBox {
hint,
boxConstraints.copyWith(minWidth: inputWidth, maxWidth: inputWidth),
);
boxToBaseline[counter] = _layoutLineBox(counter, boxConstraints);
boxToBaseline[counter] = _layoutLineBox(counter, contentConstraints);

// 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(
maxWidth: math.max(0.0, boxConstraints.maxWidth
- _boxSize(icon).width
- _boxSize(counter).width
- contentPadding.horizontal,
),
contentConstraints.copyWith(
maxWidth: math.max(0.0, contentConstraints.maxWidth - _boxSize(counter).width),
),
);

Expand Down Expand Up @@ -1267,15 +1269,45 @@ class _RenderDecoration extends RenderBox {

@override
double computeMinIntrinsicHeight(double width) {
double subtextHeight = _lineHeight(width, <RenderBox?>[helperError, counter]);
final double iconHeight = _minHeight(icon, width);
final double iconWidth = _minWidth(icon, iconHeight);

width = math.max(width - iconWidth, 0.0);

final double prefixIconHeight = _minHeight(prefixIcon, width);
final double prefixIconWidth = _minWidth(prefixIcon, prefixIconHeight);

final double suffixIconHeight = _minHeight(suffixIcon, width);
final double suffixIconWidth = _minWidth(suffixIcon, suffixIconHeight);

width = math.max(width - contentPadding.horizontal, 0.0);

final double counterHeight = _minHeight(counter, width);
final double counterWidth = _minWidth(counter, counterHeight);

final double helperErrorAvailableWidth = math.max(width - counterWidth, 0.0);
final double helperErrorHeight = _minHeight(helperError, helperErrorAvailableWidth);
double subtextHeight = math.max(counterHeight, helperErrorHeight);
if (subtextHeight > 0.0)
subtextHeight += subtextGap;

final double prefixHeight = _minHeight(prefix, width);
final double prefixWidth = _minWidth(prefix, prefixHeight);

final double suffixHeight = _minHeight(suffix, width);
final double suffixWidth = _minWidth(suffix, suffixHeight);

final double availableInputWidth = math.max(width - prefixWidth - suffixWidth - prefixIconWidth - suffixIconWidth, 0.0);
final double inputHeight = _lineHeight(availableInputWidth, <RenderBox?>[input, hint]);
final double inputMaxHeight = <double>[inputHeight, prefixHeight, suffixHeight].reduce(math.max);

final Offset densityOffset = decoration.visualDensity!.baseSizeAdjustment;
final double containerHeight = contentPadding.top
final double contentHeight = contentPadding.top
+ (label == null ? 0.0 : decoration.floatingLabelHeight)
+ _lineHeight(width, <RenderBox?>[prefix, input, suffix])
+ inputMaxHeight
+ contentPadding.bottom
+ densityOffset.dy;
final double containerHeight = <double>[iconHeight, contentHeight, prefixIconHeight, suffixIconHeight].reduce(math.max);
final double minContainerHeight = decoration.isDense! || expands
? 0.0
: kMinInteractiveDimension;
Expand Down
140 changes: 140 additions & 0 deletions packages/flutter/test/material/input_decorator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5023,6 +5023,146 @@ void main() {
expect(tester.takeException(), isNull);
});

testWidgets('min intrinsic height for TextField with prefix icon', (WidgetTester tester) async {
// Regression test for: https://github.com/flutter/flutter/issues/87403
await tester.pumpWidget(MaterialApp(
home: Material(
child: Center(
child: SizedBox(
width: 100.0,
child: IntrinsicHeight(
child: Column(
children: <Widget>[
TextField(
controller: TextEditingController(text: 'input'),
maxLines: null,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.search),
),
),
],
),
),
),
),
),
));

expect(tester.takeException(), isNull);
});

testWidgets('min intrinsic height for TextField with suffix icon', (WidgetTester tester) async {
// Regression test for: https://github.com/flutter/flutter/issues/87403
await tester.pumpWidget(MaterialApp(
home: Material(
child: Center(
child: SizedBox(
width: 100.0,
child: IntrinsicHeight(
child: Column(
children: <Widget>[
TextField(
controller: TextEditingController(text: 'input'),
maxLines: null,
decoration: const InputDecoration(
suffixIcon: Icon(Icons.search),
),
),
],
),
),
),
),
),
));

expect(tester.takeException(), isNull);
});

testWidgets('min intrinsic height for TextField with prefix', (WidgetTester tester) async {
// Regression test for: https://github.com/flutter/flutter/issues/87403
await tester.pumpWidget(MaterialApp(
home: Material(
child: Center(
child: SizedBox(
width: 100.0,
child: IntrinsicHeight(
child: Column(
children: <Widget>[
TextField(
controller: TextEditingController(text: 'input'),
maxLines: null,
decoration: const InputDecoration(
prefix: Text('prefix'),
),
),
],
),
),
),
),
),
));

expect(tester.takeException(), isNull);
});

testWidgets('min intrinsic height for TextField with suffix', (WidgetTester tester) async {
// Regression test for: https://github.com/flutter/flutter/issues/87403
await tester.pumpWidget(MaterialApp(
home: Material(
child: Center(
child: SizedBox(
width: 100.0,
child: IntrinsicHeight(
child: Column(
children: <Widget>[
TextField(
controller: TextEditingController(text: 'input'),
maxLines: null,
decoration: const InputDecoration(
suffix: Text('suffix'),
),
),
],
),
),
),
),
),
));

expect(tester.takeException(), isNull);
});

testWidgets('min intrinsic height for TextField with icon', (WidgetTester tester) async {
// Regression test for: https://github.com/flutter/flutter/issues/87403
await tester.pumpWidget(MaterialApp(
home: Material(
child: Center(
child: SizedBox(
width: 100.0,
child: IntrinsicHeight(
child: Column(
children: <Widget>[
TextField(
controller: TextEditingController(text: 'input'),
maxLines: null,
decoration: const InputDecoration(
icon: Icon(Icons.search),
),
),
],
),
),
),
),
),
));

expect(tester.takeException(), isNull);
});

testWidgets('InputDecorationTheme floatingLabelStyle overrides label widget styles when the widget is a text widget (focused)', (WidgetTester tester) async {
const TextStyle style16 = TextStyle(fontFamily: 'Ahem', fontSize: 16.0);
final TextStyle floatingLabelStyle = style16.merge(const TextStyle(color: Colors.indigo));
Expand Down

0 comments on commit 93de90b

Please sign in to comment.