Unverified Commit 924e48ee authored by Justin McCandless's avatar Justin McCandless Committed by GitHub

Increase TextField's minimum height from 40 to 48 (#42449)

This is being done to match the Material spec. It will likely break many visual diff tests.
parent 3cd8c314
...@@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart'; ...@@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'colors.dart'; import 'colors.dart';
import 'constants.dart';
import 'input_border.dart'; import 'input_border.dart';
import 'theme.dart'; import 'theme.dart';
...@@ -496,6 +497,7 @@ class _Decoration { ...@@ -496,6 +497,7 @@ class _Decoration {
this.counter, this.counter,
this.container, this.container,
this.alignLabelWithHint, this.alignLabelWithHint,
this.isDense,
}) : assert(contentPadding != null), }) : assert(contentPadding != null),
assert(isCollapsed != null), assert(isCollapsed != null),
assert(floatingLabelHeight != null), assert(floatingLabelHeight != null),
...@@ -508,6 +510,7 @@ class _Decoration { ...@@ -508,6 +510,7 @@ class _Decoration {
final InputBorder border; final InputBorder border;
final _InputBorderGap borderGap; final _InputBorderGap borderGap;
final bool alignLabelWithHint; final bool alignLabelWithHint;
final bool isDense;
final Widget icon; final Widget icon;
final Widget input; final Widget input;
final Widget label; final Widget label;
...@@ -1037,10 +1040,19 @@ class _RenderDecoration extends RenderBox { ...@@ -1037,10 +1040,19 @@ class _RenderDecoration extends RenderBox {
+ fixBelowInput + fixBelowInput
+ contentPadding.bottom, + contentPadding.bottom,
); );
final double minContainerHeight = decoration.isDense || expands
? 0.0
: kMinInteractiveDimension;
final double maxContainerHeight = boxConstraints.maxHeight - bottomHeight; final double maxContainerHeight = boxConstraints.maxHeight - bottomHeight;
final double containerHeight = expands final double containerHeight = expands
? maxContainerHeight ? maxContainerHeight
: math.min(contentHeight, maxContainerHeight); : math.min(math.max(contentHeight, minContainerHeight), maxContainerHeight);
// Ensure the text is vertically centered in cases where the content is
// shorter than kMinInteractiveDimension.
final double interactiveAdjustment = minContainerHeight > contentHeight
? (minContainerHeight - contentHeight) / 2.0
: 0.0;
// Try to consider the prefix/suffix as part of the text when aligning it. // Try to consider the prefix/suffix as part of the text when aligning it.
// If the prefix/suffix overflows however, allow it to extend outside of the // If the prefix/suffix overflows however, allow it to extend outside of the
...@@ -1058,7 +1070,8 @@ class _RenderDecoration extends RenderBox { ...@@ -1058,7 +1070,8 @@ class _RenderDecoration extends RenderBox {
final double topInputBaseline = contentPadding.top final double topInputBaseline = contentPadding.top
+ topHeight + topHeight
+ inputInternalBaseline + inputInternalBaseline
+ baselineAdjustment; + baselineAdjustment
+ interactiveAdjustment;
final double maxContentHeight = containerHeight final double maxContentHeight = containerHeight
- contentPadding.top - contentPadding.top
- topHeight - topHeight
...@@ -2156,7 +2169,10 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat ...@@ -2156,7 +2169,10 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
widthFactor: 1.0, widthFactor: 1.0,
heightFactor: 1.0, heightFactor: 1.0,
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 48.0, minHeight: 48.0), constraints: const BoxConstraints(
minWidth: kMinInteractiveDimension,
minHeight: kMinInteractiveDimension,
),
child: IconTheme.merge( child: IconTheme.merge(
data: IconThemeData( data: IconThemeData(
color: iconColor, color: iconColor,
...@@ -2172,7 +2188,10 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat ...@@ -2172,7 +2188,10 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
widthFactor: 1.0, widthFactor: 1.0,
heightFactor: 1.0, heightFactor: 1.0,
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 48.0, minHeight: 48.0), constraints: const BoxConstraints(
minWidth: kMinInteractiveDimension,
minHeight: kMinInteractiveDimension,
),
child: IconTheme.merge( child: IconTheme.merge(
data: IconThemeData( data: IconThemeData(
color: iconColor, color: iconColor,
...@@ -2253,6 +2272,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat ...@@ -2253,6 +2272,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
input: widget.child, input: widget.child,
label: label, label: label,
alignLabelWithHint: decoration.alignLabelWithHint, alignLabelWithHint: decoration.alignLabelWithHint,
isDense: decoration.isDense,
hint: hint, hint: hint,
prefix: prefix, prefix: prefix,
suffix: suffix, suffix: suffix,
......
...@@ -509,12 +509,12 @@ void main() { ...@@ -509,12 +509,12 @@ void main() {
), ),
); );
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 40.0)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension));
expect(tester.getTopLeft(find.text('text')).dy, 12.0); expect(tester.getTopLeft(find.text('text')).dy, 16.0);
expect(tester.getBottomLeft(find.text('text')).dy, 28.0); expect(tester.getBottomLeft(find.text('text')).dy, 32.0);
expect(tester.getTopLeft(find.text('hint')).dy, 12.0); expect(tester.getTopLeft(find.text('hint')).dy, 16.0);
expect(tester.getBottomLeft(find.text('hint')).dy, 28.0); expect(tester.getBottomLeft(find.text('hint')).dy, 32.0);
expect(getBorderBottom(tester), 40.0); expect(getBorderBottom(tester), 48.0);
expect(getBorderWeight(tester), 1.0); expect(getBorderWeight(tester), 1.0);
expect(tester.getSize(find.text('hint')).width, tester.getSize(find.text('text')).width); expect(tester.getSize(find.text('hint')).width, tester.getSize(find.text('text')).width);
...@@ -1144,14 +1144,14 @@ void main() { ...@@ -1144,14 +1144,14 @@ void main() {
// The prefix and suffix wrap the input text and are left and right justified // The prefix and suffix wrap the input text and are left and right justified
// respectively. They should have the same height as the input text (16). // respectively. They should have the same height as the input text (16).
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 40.0)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension));
expect(tester.getSize(find.text('text')).height, 16.0); expect(tester.getSize(find.text('text')).height, 16.0);
expect(tester.getSize(find.text('p')).height, 16.0); expect(tester.getSize(find.text('p')).height, 16.0);
expect(tester.getSize(find.text('s')).height, 16.0); expect(tester.getSize(find.text('s')).height, 16.0);
expect(tester.getTopLeft(find.text('text')).dy, 12.0); expect(tester.getTopLeft(find.text('text')).dy, 16.0);
expect(tester.getTopLeft(find.text('p')).dy, 12.0); expect(tester.getTopLeft(find.text('p')).dy, 16.0);
expect(tester.getTopLeft(find.text('p')).dx, 12.0); expect(tester.getTopLeft(find.text('p')).dx, 12.0);
expect(tester.getTopLeft(find.text('s')).dy, 12.0); expect(tester.getTopLeft(find.text('s')).dy, 16.0);
expect(tester.getTopRight(find.text('s')).dx, 788.0); expect(tester.getTopRight(find.text('s')).dx, 788.0);
// layout is a row: [p text s] // layout is a row: [p text s]
...@@ -1179,18 +1179,18 @@ void main() { ...@@ -1179,18 +1179,18 @@ void main() {
// 16 - input text (ahem font size 16dps) // 16 - input text (ahem font size 16dps)
// 12 - bottom padding // 12 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 40.0)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension));
expect(tester.getSize(find.text('text')).height, 16.0); expect(tester.getSize(find.text('text')).height, 16.0);
expect(tester.getSize(find.text('p')).height, 16.0); expect(tester.getSize(find.text('p')).height, 16.0);
expect(tester.getSize(find.text('s')).height, 16.0); expect(tester.getSize(find.text('s')).height, 16.0);
expect(tester.getTopLeft(find.text('text')).dy, 12.0); expect(tester.getTopLeft(find.text('text')).dy, 16.0);
expect(tester.getTopLeft(find.text('p')).dy, 12.0); expect(tester.getTopLeft(find.text('p')).dy, 16.0);
expect(tester.getTopLeft(find.text('s')).dy, 12.0); expect(tester.getTopLeft(find.text('s')).dy, 16.0);
expect(tester.getTopRight(find.text('s')).dx, 788.0); expect(tester.getTopRight(find.text('s')).dx, 788.0);
expect(tester.getSize(find.byType(Icon)).height, 24.0); expect(tester.getSize(find.byType(Icon)).height, 24.0);
// The 24dps high icon is centered on the 16dps high input line // The 24dps high icon is centered on the 16dps high input line
expect(tester.getTopLeft(find.byType(Icon)).dy, 8.0); expect(tester.getTopLeft(find.byType(Icon)).dy, 12.0);
// layout is a row: [icon, p text s] // layout is a row: [icon, p text s]
expect(tester.getTopLeft(find.byType(Icon)).dx, 0.0); expect(tester.getTopLeft(find.byType(Icon)).dx, 0.0);
...@@ -1939,10 +1939,10 @@ void main() { ...@@ -1939,10 +1939,10 @@ void main() {
), ),
); );
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 44.0)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
expect(tester.getTopLeft(find.text('text')).dy, 13.0); expect(tester.getTopLeft(find.text('text')).dy, 15.0);
expect(tester.getBottomLeft(find.text('text')).dy, 29.0); expect(tester.getBottomLeft(find.text('text')).dy, 31.0);
expect(getBorderBottom(tester), 44.0); expect(getBorderBottom(tester), 48.0);
expect(getBorderWeight(tester), 1.0); expect(getBorderWeight(tester), 1.0);
}); });
...@@ -1960,10 +1960,10 @@ void main() { ...@@ -1960,10 +1960,10 @@ void main() {
), ),
); );
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 44.0)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension));
expect(tester.getTopLeft(find.text('text')).dy, 13.0); expect(tester.getTopLeft(find.text('text')).dy, 15.0);
expect(tester.getBottomLeft(find.text('text')).dy, 29.0); expect(tester.getBottomLeft(find.text('text')).dy, 31.0);
expect(getBorderBottom(tester), 44.0); expect(getBorderBottom(tester), 48.0);
expect(getBorderWeight(tester), 1.0); expect(getBorderWeight(tester), 1.0);
}); });
...@@ -2098,7 +2098,7 @@ void main() { ...@@ -2098,7 +2098,7 @@ void main() {
// Margin for text decoration is 12 when filled // Margin for text decoration is 12 when filled
// (dx) - 12 = (text offset)x. // (dx) - 12 = (text offset)x.
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 60.0)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 68.0));
final double dx = tester.getRect(find.byType(InputDecorator)).right; final double dx = tester.getRect(find.byType(InputDecorator)).right;
expect(tester.getRect(find.text('test')).right, dx - 12.0); expect(tester.getRect(find.text('test')).right, dx - 12.0);
}); });
...@@ -2118,7 +2118,7 @@ void main() { ...@@ -2118,7 +2118,7 @@ void main() {
// Margin for text decoration is 12 when filled and top left offset is (0, 0) // Margin for text decoration is 12 when filled and top left offset is (0, 0)
// 0 + 12 = 12. // 0 + 12 = 12.
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 60.0)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 68.0));
expect(tester.getRect(find.text('test')).left, 12.0); expect(tester.getRect(find.text('test')).left, 12.0);
}); });
...@@ -2236,13 +2236,13 @@ void main() { ...@@ -2236,13 +2236,13 @@ void main() {
// 16 - input text (ahem font size 16dps) // 16 - input text (ahem font size 16dps)
// 12 - bottom padding // 12 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 40.0)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension)); // 40 bumped up to minimum.
expect(tester.getSize(find.text('text')).height, 16.0); expect(tester.getSize(find.text('text')).height, 16.0);
expect(tester.getSize(find.text('p')).height, 16.0); expect(tester.getSize(find.text('p')).height, 16.0);
expect(tester.getSize(find.text('s')).height, 16.0); expect(tester.getSize(find.text('s')).height, 16.0);
expect(tester.getTopLeft(find.text('text')).dy, 12.0); expect(tester.getTopLeft(find.text('text')).dy, 16.0);
expect(tester.getTopLeft(find.text('p')).dy, 12.0); expect(tester.getTopLeft(find.text('p')).dy, 16.0);
expect(tester.getTopLeft(find.text('s')).dy, 12.0); expect(tester.getTopLeft(find.text('s')).dy, 16.0);
// layout is a row: [s text p] // layout is a row: [s text p]
expect(tester.getTopLeft(find.text('s')).dx, 12.0); expect(tester.getTopLeft(find.text('s')).dx, 12.0);
...@@ -2339,10 +2339,10 @@ void main() { ...@@ -2339,10 +2339,10 @@ void main() {
// 16 - input text (ahem font size 16dps) // 16 - input text (ahem font size 16dps)
// 12 - bottom padding // 12 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 40.0)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension)); // 40 bumped up to minimum.
expect(tester.getSize(find.text('text')).height, 16.0); expect(tester.getSize(find.text('text')).height, 16.0);
expect(tester.getTopLeft(find.text('text')).dy, 12.0); expect(tester.getTopLeft(find.text('text')).dy, 16.0);
expect(getBorderBottom(tester), 40.0); expect(getBorderBottom(tester), kMinInteractiveDimension); // 40 bumped up to minimum.
expect(getBorderWeight(tester), 1.0); expect(getBorderWeight(tester), 1.0);
}, skip: isBrowser); }, skip: isBrowser);
...@@ -2360,9 +2360,9 @@ void main() { ...@@ -2360,9 +2360,9 @@ void main() {
// Overall height for this InputDecorator is 16dps: // Overall height for this InputDecorator is 16dps:
// 16 - input text (ahem font size 16dps) // 16 - input text (ahem font size 16dps)
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 16.0)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension)); // 16 bumped up to minimum.
expect(tester.getSize(find.text('text')).height, 16.0); expect(tester.getSize(find.text('text')).height, 16.0);
expect(tester.getTopLeft(find.text('text')).dy, 0.0); expect(tester.getTopLeft(find.text('text')).dy, 16.0);
expect(getOpacity(tester, 'hint'), 0.0); expect(getOpacity(tester, 'hint'), 0.0);
expect(getBorderWeight(tester), 0.0); expect(getBorderWeight(tester), 0.0);
...@@ -2378,11 +2378,11 @@ void main() { ...@@ -2378,11 +2378,11 @@ void main() {
); );
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 16.0)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension));
expect(tester.getSize(find.text('text')).height, 16.0); expect(tester.getSize(find.text('text')).height, 16.0);
expect(tester.getTopLeft(find.text('text')).dy, 0.0); expect(tester.getTopLeft(find.text('text')).dy, 16.0);
expect(tester.getSize(find.text('hint')).height, 16.0); expect(tester.getSize(find.text('hint')).height, 16.0);
expect(tester.getTopLeft(find.text('hint')).dy, 0.0); expect(tester.getTopLeft(find.text('hint')).dy, 16.0);
expect(getBorderWeight(tester), 0.0); expect(getBorderWeight(tester), 0.0);
}, skip: isBrowser); }, skip: isBrowser);
...@@ -2418,13 +2418,13 @@ void main() { ...@@ -2418,13 +2418,13 @@ void main() {
// 10 - label (ahem font size 10dps) // 10 - label (ahem font size 10dps)
// 17.75 - bottom padding (empty input text still appears here) // 17.75 - bottom padding (empty input text still appears here)
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 45.5)); expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension)); // 45.5 bumped up to minimum.
expect(tester.getSize(find.text('hint')).height, 10.0); expect(tester.getSize(find.text('hint')).height, 10.0);
expect(tester.getSize(find.text('label')).height, 10.0); expect(tester.getSize(find.text('label')).height, 10.0);
expect(tester.getSize(find.text('text')).height, 10.0); expect(tester.getSize(find.text('text')).height, 10.0);
expect(tester.getTopLeft(find.text('hint')).dy, 23.5); expect(tester.getTopLeft(find.text('hint')).dy, 24.75);
expect(tester.getTopLeft(find.text('label')).dy, 17.75); expect(tester.getTopLeft(find.text('label')).dy, 19.0);
expect(tester.getTopLeft(find.text('text')).dy, 23.5); expect(tester.getTopLeft(find.text('text')).dy, 24.75);
}, skip: isBrowser); }, skip: isBrowser);
testWidgets('InputDecorator with empty style overrides', (WidgetTester tester) async { testWidgets('InputDecorator with empty style overrides', (WidgetTester tester) async {
......
...@@ -519,10 +519,10 @@ void main() { ...@@ -519,10 +519,10 @@ void main() {
// This tap just puts the cursor somewhere different than where the double // This tap just puts the cursor somewhere different than where the double
// tap will occur to test that the double tap moves the existing cursor first. // tap will occur to test that the double tap moves the existing cursor first.
await tester.tapAt(textfieldStart + const Offset(50.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
// First tap moved the cursor. // First tap moved the cursor.
expect( expect(
...@@ -530,7 +530,7 @@ void main() { ...@@ -530,7 +530,7 @@ void main() {
const TextSelection.collapsed( const TextSelection.collapsed(
offset: 8, affinity: TextAffinity.downstream), offset: 8, affinity: TextAffinity.downstream),
); );
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(); await tester.pump();
// Second tap selects the word around the cursor. // Second tap selects the word around the cursor.
...@@ -566,10 +566,10 @@ void main() { ...@@ -566,10 +566,10 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(); await tester.pump();
// Selected text shows 'COPY', and not 'PASTE', 'CUT', 'SELECT ALL'. // Selected text shows 'COPY', and not 'PASTE', 'CUT', 'SELECT ALL'.
...@@ -2870,7 +2870,7 @@ void main() { ...@@ -2870,7 +2870,7 @@ void main() {
), ),
); );
expect(tester.getTopLeft(find.text('hint')), equals(tester.getTopLeft(find.byType(TextField)))); expect(tester.getTopLeft(find.text('hint')), equals(tester.getTopLeft(find.byType(EditableText))));
}); });
testWidgets('Can align to center', (WidgetTester tester) async { testWidgets('Can align to center', (WidgetTester tester) async {
...@@ -5523,7 +5523,7 @@ void main() { ...@@ -5523,7 +5523,7 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.tapAt(textfieldStart + const Offset(50.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(); await tester.pump();
// We moved the cursor. // We moved the cursor.
...@@ -5557,7 +5557,7 @@ void main() { ...@@ -5557,7 +5557,7 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.tapAt(textfieldStart + const Offset(50.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(); await tester.pump();
// We moved the cursor. // We moved the cursor.
...@@ -5592,9 +5592,9 @@ void main() { ...@@ -5592,9 +5592,9 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.tapAt(textfieldStart + const Offset(50.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
await tester.tapAt(textfieldStart + const Offset(50.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(); await tester.pump();
// Plain collapsed selection. // Plain collapsed selection.
...@@ -5631,17 +5631,17 @@ void main() { ...@@ -5631,17 +5631,17 @@ void main() {
// This tap just puts the cursor somewhere different than where the double // This tap just puts the cursor somewhere different than where the double
// tap will occur to test that the double tap moves the existing cursor first. // tap will occur to test that the double tap moves the existing cursor first.
await tester.tapAt(textfieldStart + const Offset(50.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
// First tap moved the cursor. // First tap moved the cursor.
expect( expect(
controller.selection, controller.selection,
const TextSelection.collapsed(offset: 8, affinity: TextAffinity.downstream), const TextSelection.collapsed(offset: 8, affinity: TextAffinity.downstream),
); );
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(); await tester.pump();
// Second tap selects the word around the cursor. // Second tap selects the word around the cursor.
...@@ -5677,17 +5677,17 @@ void main() { ...@@ -5677,17 +5677,17 @@ void main() {
// This tap just puts the cursor somewhere different than where the double // This tap just puts the cursor somewhere different than where the double
// tap will occur to test that the double tap moves the existing cursor first. // tap will occur to test that the double tap moves the existing cursor first.
await tester.tapAt(textfieldStart + const Offset(50.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
// First tap moved the cursor. // First tap moved the cursor.
expect( expect(
controller.selection, controller.selection,
const TextSelection.collapsed(offset: 9), const TextSelection.collapsed(offset: 9),
); );
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(); await tester.pump();
// Second tap selects the word around the cursor. // Second tap selects the word around the cursor.
...@@ -5896,10 +5896,10 @@ void main() { ...@@ -5896,10 +5896,10 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
final TestGesture gesture = final TestGesture gesture =
await tester.startGesture(textfieldStart + const Offset(150.0, 5.0)); await tester.startGesture(textfieldStart + const Offset(150.0, 9.0));
// Hold the press. // Hold the press.
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
...@@ -5945,17 +5945,17 @@ void main() { ...@@ -5945,17 +5945,17 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
// First tap moved the cursor. // First tap moved the cursor.
expect( expect(
controller.selection, controller.selection,
const TextSelection.collapsed(offset: 8, affinity: TextAffinity.downstream), const TextSelection.collapsed(offset: 8, affinity: TextAffinity.downstream),
); );
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
await tester.tapAt(textfieldStart + const Offset(100.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(100.0, 9.0));
await tester.pump(); await tester.pump();
// Plain collapsed selection at the edge of first word. In iOS 12, the // Plain collapsed selection at the edge of first word. In iOS 12, the
...@@ -5993,7 +5993,7 @@ void main() { ...@@ -5993,7 +5993,7 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.longPressAt(textfieldStart + const Offset(50.0, 5.0)); await tester.longPressAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(); await tester.pump();
// Collapsed cursor for iOS long press. // Collapsed cursor for iOS long press.
...@@ -6027,7 +6027,7 @@ void main() { ...@@ -6027,7 +6027,7 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.longPressAt(textfieldStart + const Offset(50.0, 5.0)); await tester.longPressAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(); await tester.pump();
expect( expect(
...@@ -6061,10 +6061,10 @@ void main() { ...@@ -6061,10 +6061,10 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.longPressAt(textfieldStart + const Offset(50.0, 5.0)); await tester.longPressAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
await tester.tapAt(textfieldStart + const Offset(50.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(); await tester.pump();
// We ended up moving the cursor to the edge of the same word and dismissed // We ended up moving the cursor to the edge of the same word and dismissed
...@@ -6101,7 +6101,7 @@ void main() { ...@@ -6101,7 +6101,7 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
final TestGesture gesture = final TestGesture gesture =
await tester.startGesture(textfieldStart + const Offset(50.0, 5.0)); await tester.startGesture(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
// Long press on iOS shows collapsed selection cursor. // Long press on iOS shows collapsed selection cursor.
...@@ -6258,17 +6258,17 @@ void main() { ...@@ -6258,17 +6258,17 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
// First tap moved the cursor to the beginning of the second word. // First tap moved the cursor to the beginning of the second word.
expect( expect(
controller.selection, controller.selection,
const TextSelection.collapsed(offset: 8, affinity: TextAffinity.downstream), const TextSelection.collapsed(offset: 8, affinity: TextAffinity.downstream),
); );
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
await tester.longPressAt(textfieldStart + const Offset(100.0, 5.0)); await tester.longPressAt(textfieldStart + const Offset(100.0, 9.0));
await tester.pump(); await tester.pump();
// Plain collapsed selection at the exact tap position. // Plain collapsed selection at the exact tap position.
...@@ -6303,17 +6303,17 @@ void main() { ...@@ -6303,17 +6303,17 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.longPressAt(textfieldStart + const Offset(50.0, 5.0)); await tester.longPressAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
// First tap moved the cursor. // First tap moved the cursor.
expect( expect(
controller.selection, controller.selection,
const TextSelection.collapsed(offset: 8, affinity: TextAffinity.downstream), const TextSelection.collapsed(offset: 8, affinity: TextAffinity.downstream),
); );
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(); await tester.pump();
// Double tap selection. // Double tap selection.
...@@ -6346,13 +6346,13 @@ void main() { ...@@ -6346,13 +6346,13 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
await tester.tapAt(textfieldStart + const Offset(50.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect( expect(
controller.selection, controller.selection,
const TextSelection.collapsed(offset: 7, affinity: TextAffinity.upstream), const TextSelection.collapsed(offset: 7, affinity: TextAffinity.upstream),
); );
await tester.tapAt(textfieldStart + const Offset(50.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect( expect(
controller.selection, controller.selection,
...@@ -6361,14 +6361,14 @@ void main() { ...@@ -6361,14 +6361,14 @@ void main() {
expect(find.byType(CupertinoButton), findsNWidgets(3)); expect(find.byType(CupertinoButton), findsNWidgets(3));
// Double tap selecting the same word somewhere else is fine. // Double tap selecting the same word somewhere else is fine.
await tester.tapAt(textfieldStart + const Offset(100.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(100.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
// First tap moved the cursor. // First tap moved the cursor.
expect( expect(
controller.selection, controller.selection,
const TextSelection.collapsed(offset: 7, affinity: TextAffinity.upstream), const TextSelection.collapsed(offset: 7, affinity: TextAffinity.upstream),
); );
await tester.tapAt(textfieldStart + const Offset(100.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(100.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect( expect(
controller.selection, controller.selection,
...@@ -6376,14 +6376,14 @@ void main() { ...@@ -6376,14 +6376,14 @@ void main() {
); );
expect(find.byType(CupertinoButton), findsNWidgets(3)); expect(find.byType(CupertinoButton), findsNWidgets(3));
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
// First tap moved the cursor. // First tap moved the cursor.
expect( expect(
controller.selection, controller.selection,
const TextSelection.collapsed(offset: 8, affinity: TextAffinity.downstream), const TextSelection.collapsed(offset: 8, affinity: TextAffinity.downstream),
); );
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0)); await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect( expect(
controller.selection, controller.selection,
...@@ -6407,7 +6407,7 @@ void main() { ...@@ -6407,7 +6407,7 @@ void main() {
), ),
); );
final Offset offset = tester.getTopLeft(find.byType(TextField)) + const Offset(150.0, 5.0); final Offset offset = tester.getTopLeft(find.byType(TextField)) + const Offset(150.0, 9.0);
const int pointerValue = 1; const int pointerValue = 1;
final TestGesture gesture = await tester.createGesture(); final TestGesture gesture = await tester.createGesture();
...@@ -6421,7 +6421,7 @@ void main() { ...@@ -6421,7 +6421,7 @@ void main() {
pressureMin: 0.0, pressureMin: 0.0,
), ),
); );
await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: offset + const Offset(150.0, 5.0), pressure: 0.5, pressureMin: 0, pressureMax: 1)); await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: offset + const Offset(150.0, 9.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
// We don't want this gesture to select any word on Android. // We don't want this gesture to select any word on Android.
expect(controller.selection, const TextSelection.collapsed(offset: -1)); expect(controller.selection, const TextSelection.collapsed(offset: -1));
...@@ -6449,7 +6449,7 @@ void main() { ...@@ -6449,7 +6449,7 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
const int pointerValue = 1; const int pointerValue = 1;
final Offset offset = textfieldStart + const Offset(150.0, 5.0); final Offset offset = textfieldStart + const Offset(150.0, 9.0);
final TestGesture gesture = await tester.createGesture(); final TestGesture gesture = await tester.createGesture();
await gesture.downWithCustomEvent( await gesture.downWithCustomEvent(
offset, offset,
...@@ -6462,7 +6462,7 @@ void main() { ...@@ -6462,7 +6462,7 @@ void main() {
), ),
); );
await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: textfieldStart + const Offset(150.0, 5.0), pressure: 0.5, pressureMin: 0, pressureMax: 1)); await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: textfieldStart + const Offset(150.0, 9.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
// We expect the force press to select a word at the given location. // We expect the force press to select a word at the given location.
expect( expect(
controller.selection, controller.selection,
...@@ -6492,7 +6492,7 @@ void main() { ...@@ -6492,7 +6492,7 @@ void main() {
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField)); final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
const int pointerValue = 1; const int pointerValue = 1;
final Offset offset = textfieldStart + const Offset(150.0, 5.0); final Offset offset = textfieldStart + const Offset(150.0, 9.0);
final TestGesture gesture = await tester.createGesture(); final TestGesture gesture = await tester.createGesture();
await gesture.downWithCustomEvent( await gesture.downWithCustomEvent(
offset, offset,
...@@ -6506,7 +6506,7 @@ void main() { ...@@ -6506,7 +6506,7 @@ void main() {
), ),
); );
await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: textfieldStart + const Offset(150.0, 5.0), pressure: 0.5, pressureMin: 0, pressureMax: 1)); await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: textfieldStart + const Offset(150.0, 9.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
await gesture.up(); await gesture.up();
// The event should fallback to a normal tap and move the cursor. // The event should fallback to a normal tap and move the cursor.
// Single taps selects the edge of the word. // Single taps selects the edge of the word.
...@@ -6602,9 +6602,11 @@ void main() { ...@@ -6602,9 +6602,11 @@ void main() {
expect( expect(
tester.getSize(find.byType(TextField)), tester.getSize(find.byType(TextField)),
// This is the height of the decoration (24) plus the metrics from the default // The TextField will be as tall as the decoration (24) plus the metrics
// TextStyle of the theme (16). // from the default TextStyle of the theme (16), or 40 altogether.
const Size(800, 40), // Because this is less than the kMinInteractiveDimension, it will be
// increased to that value (48).
const Size(800, kMinInteractiveDimension),
); );
}, },
); );
...@@ -6629,7 +6631,7 @@ void main() { ...@@ -6629,7 +6631,7 @@ void main() {
tester.getSize(find.byType(TextField)), tester.getSize(find.byType(TextField)),
// Strut should inherit the TextStyle.fontSize by default and produce the // Strut should inherit the TextStyle.fontSize by default and produce the
// same height as if it were disabled. // same height as if it were disabled.
const Size(800, 44), const Size(800, kMinInteractiveDimension), // Because 44 < 48.
); );
await tester.pumpWidget( await tester.pumpWidget(
...@@ -6649,7 +6651,7 @@ void main() { ...@@ -6649,7 +6651,7 @@ void main() {
expect( expect(
tester.getSize(find.byType(TextField)), tester.getSize(find.byType(TextField)),
// The height here should match the previous version with strut enabled. // The height here should match the previous version with strut enabled.
const Size(800, 44), const Size(800, kMinInteractiveDimension), // Because 44 < 48.
); );
}, },
); );
...@@ -7235,7 +7237,6 @@ void main() { ...@@ -7235,7 +7237,6 @@ void main() {
testWidgets('when TextField would be blocked by keyboard, it is shown with enough space for the selection handle', (WidgetTester tester) async { testWidgets('when TextField would be blocked by keyboard, it is shown with enough space for the selection handle', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
final TextEditingController controller = TextEditingController();
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(), theme: ThemeData(),
...@@ -7245,7 +7246,7 @@ void main() { ...@@ -7245,7 +7246,7 @@ void main() {
controller: scrollController, controller: scrollController,
children: <Widget>[ children: <Widget>[
Container(height: 579), // Push field almost off screen. Container(height: 579), // Push field almost off screen.
TextField(controller: controller), const TextField(),
Container(height: 1000), Container(height: 1000),
], ],
), ),
...@@ -7255,12 +7256,62 @@ void main() { ...@@ -7255,12 +7256,62 @@ void main() {
// Tap the TextField to put the cursor into it and bring it into view. // Tap the TextField to put the cursor into it and bring it into view.
expect(scrollController.offset, 0.0); expect(scrollController.offset, 0.0);
await tester.tap(find.byType(TextField)); await tester.tapAt(tester.getTopLeft(find.byType(TextField)));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
// The ListView has scrolled to keep the TextField and cursor handle // The ListView has scrolled to keep the TextField and cursor handle
// visible. // visible.
expect(scrollController.offset, 44.0); expect(scrollController.offset, 48.0);
});
group('height', () {
testWidgets('By default, TextField is at least kMinInteractiveDimension high', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(),
home: const Scaffold(
body: Center(
child: TextField(),
),
),
));
final RenderBox renderBox = tester.renderObject(find.byType(TextField));
expect(renderBox.size.height, greaterThanOrEqualTo(kMinInteractiveDimension));
});
testWidgets('When text is very small, TextField still doesn\'t go below kMinInteractiveDimension height', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(),
home: const Scaffold(
body: Center(
child: TextField(
style: TextStyle(fontSize: 2.0),
),
),
),
));
final RenderBox renderBox = tester.renderObject(find.byType(TextField));
expect(renderBox.size.height, kMinInteractiveDimension);
});
testWidgets('When isDense, TextField can go below kMinInteractiveDimension height', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(),
home: const Scaffold(
body: Center(
child: TextField(
decoration: InputDecoration(
isDense: true,
),
),
),
),
));
final RenderBox renderBox = tester.renderObject(find.byType(TextField));
expect(renderBox.size.height, lessThan(kMinInteractiveDimension));
});
}); });
testWidgets("Arrow keys don't move input focus", (WidgetTester tester) async { testWidgets("Arrow keys don't move input focus", (WidgetTester tester) async {
final TextEditingController controller1 = TextEditingController(); final TextEditingController controller1 = 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