From 20015400f983500708cb13d8c40176176ac5beb4 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Mon, 3 Apr 2017 20:48:54 -0700 Subject: [PATCH] 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 --- .../lib/src/material/input_decorator.dart | 13 +++-- .../flutter/lib/src/rendering/editable.dart | 7 ++- .../test/material/input_decorator_test.dart | 49 +++++++++++++++++++ .../test/material/text_field_test.dart | 34 +++++++++++++ 4 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 packages/flutter/test/material/input_decorator_test.dart diff --git a/packages/flutter/lib/src/material/input_decorator.dart b/packages/flutter/lib/src/material/input_decorator.dart index 0fd03bb38a..ef430cdc7b 100644 --- a/packages/flutter/lib/src/material/input_decorator.dart +++ b/packages/flutter/lib/src/material/input_decorator.dart @@ -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: [ 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; } } diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart index 9d586006ad..75e4b22f3e 100644 --- a/packages/flutter/lib/src/rendering/editable.dart +++ b/packages/flutter/lib/src/rendering/editable.dart @@ -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 diff --git a/packages/flutter/test/material/input_decorator_test.dart b/packages/flutter/test/material/input_decorator_test.dart new file mode 100644 index 0000000000..ded1c630aa --- /dev/null +++ b/packages/flutter/test/material/input_decorator_test.dart @@ -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))); + }); +} diff --git a/packages/flutter/test/material/text_field_test.dart b/packages/flutter/test/material/text_field_test.dart index 2a460ebd58..7609d12daa 100644 --- a/packages/flutter/test/material/text_field_test.dart +++ b/packages/flutter/test/material/text_field_test.dart @@ -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)); + }); }