TextField centering should work in loose constraints (#9153)

We should always use the maxWidth from the incomming constraints to size the
text inside the editable because the EditableText itself always expands to fill
its width.

Also, make sure InputDecoration always expands horizontially (even when there's
no icon) for consistency.

Fixes #9149
This commit is contained in:
Adam Barth 2017-04-03 20:48:54 -07:00 committed by GitHub
parent a246811953
commit 20015400f9
4 changed files with 94 additions and 9 deletions

View File

@ -427,13 +427,13 @@ class InputDecorator extends StatelessWidget {
));
}
Widget result = new Stack(children: stackChildren);
final Widget stack = new Stack(children: stackChildren);
if (decoration.icon != null) {
assert(!isCollapsed);
final double iconSize = isDense ? 18.0 : 24.0;
final double iconTop = topPadding + (baseStyle.fontSize - iconSize) / 2.0;
result = new Row(
return new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
@ -448,12 +448,15 @@ class InputDecorator extends StatelessWidget {
child: decoration.icon,
),
),
new Expanded(child: result),
new Expanded(child: stack),
],
);
} else {
return new ConstrainedBox(
constraints: const BoxConstraints(minWidth: double.INFINITY),
child: stack,
);
}
return result;
}
}

View File

@ -357,10 +357,9 @@ class RenderEditable extends RenderBox {
void _layoutText() {
final double caretMargin = _kCaretGap + _kCaretWidth;
final double maxWidth = _maxLines > 1 ?
math.max(0.0, constraints.maxWidth - caretMargin) : double.INFINITY;
final double minWidth = math.max(0.0, constraints.minWidth - caretMargin);
_textPainter.layout(minWidth: minWidth, maxWidth: maxWidth);
final double availableWidth = math.max(0.0, constraints.maxWidth - caretMargin);
final double maxWidth = _maxLines > 1 ? availableWidth : double.INFINITY;
_textPainter.layout(minWidth: availableWidth, maxWidth: maxWidth);
}
@override

View File

@ -0,0 +1,49 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
void main() {
testWidgets('InputDecorator always expands', (WidgetTester tester) async {
final Key key = new UniqueKey();
await tester.pumpWidget(new Material(
child: new Center(
child: new InputDecorator(
decoration: const InputDecoration(),
child: new Container(key: key, width: 50.0, height: 60.0, color: Colors.blue),
),
),
));
expect(tester.element(find.byKey(key)).size, equals(const Size(800.0, 60.0)));
await tester.pumpWidget(new Material(
child: new Center(
child: new InputDecorator(
decoration: const InputDecoration(
icon: const Icon(Icons.add_shopping_cart),
),
child: new Container(key: key, width: 50.0, height: 60.0, color: Colors.blue),
),
),
));
expect(tester.element(find.byKey(key)).size, equals(const Size(752.0, 60.0)));
await tester.pumpWidget(new Material(
child: new Center(
child: new InputDecorator(
decoration: const InputDecoration.collapsed(
hintText: 'Hint text',
),
child: new Container(key: key, width: 50.0, height: 60.0, color: Colors.blue),
),
),
));
expect(tester.element(find.byKey(key)).size, equals(const Size(800.0, 60.0)));
});
}

View File

@ -852,4 +852,38 @@ void main() {
expect(topLeft.x, equals(399.0));
});
testWidgets('Can align to center within center', (WidgetTester tester) async {
await tester.pumpWidget(
overlay(new Center(
child: new Material(
child: new Container(
width: 300.0,
child: new Center(
child: new TextField(
textAlign: TextAlign.center,
decoration: null,
),
),
),
),
)),
);
final RenderEditable editable = findRenderEditable(tester);
Point topLeft = editable.localToGlobal(
editable.getLocalRectForCaret(new TextPosition(offset: 0)).topLeft
);
expect(topLeft.x, equals(399.0));
await tester.enterText(find.byType(EditableText), 'abcd');
await tester.pump();
topLeft = editable.localToGlobal(
editable.getLocalRectForCaret(new TextPosition(offset: 2)).topLeft
);
expect(topLeft.x, equals(399.0));
});
}