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.
This commit is contained in:
committed by
GitHub
parent
3cd8c3142c
commit
924e48eeb9
@@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'colors.dart';
|
||||
import 'constants.dart';
|
||||
import 'input_border.dart';
|
||||
import 'theme.dart';
|
||||
|
||||
@@ -496,6 +497,7 @@ class _Decoration {
|
||||
this.counter,
|
||||
this.container,
|
||||
this.alignLabelWithHint,
|
||||
this.isDense,
|
||||
}) : assert(contentPadding != null),
|
||||
assert(isCollapsed != null),
|
||||
assert(floatingLabelHeight != null),
|
||||
@@ -508,6 +510,7 @@ class _Decoration {
|
||||
final InputBorder border;
|
||||
final _InputBorderGap borderGap;
|
||||
final bool alignLabelWithHint;
|
||||
final bool isDense;
|
||||
final Widget icon;
|
||||
final Widget input;
|
||||
final Widget label;
|
||||
@@ -1037,10 +1040,19 @@ class _RenderDecoration extends RenderBox {
|
||||
+ fixBelowInput
|
||||
+ contentPadding.bottom,
|
||||
);
|
||||
final double minContainerHeight = decoration.isDense || expands
|
||||
? 0.0
|
||||
: kMinInteractiveDimension;
|
||||
final double maxContainerHeight = boxConstraints.maxHeight - bottomHeight;
|
||||
final double containerHeight = expands
|
||||
? 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.
|
||||
// If the prefix/suffix overflows however, allow it to extend outside of the
|
||||
@@ -1058,7 +1070,8 @@ class _RenderDecoration extends RenderBox {
|
||||
final double topInputBaseline = contentPadding.top
|
||||
+ topHeight
|
||||
+ inputInternalBaseline
|
||||
+ baselineAdjustment;
|
||||
+ baselineAdjustment
|
||||
+ interactiveAdjustment;
|
||||
final double maxContentHeight = containerHeight
|
||||
- contentPadding.top
|
||||
- topHeight
|
||||
@@ -2156,7 +2169,10 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
||||
widthFactor: 1.0,
|
||||
heightFactor: 1.0,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(minWidth: 48.0, minHeight: 48.0),
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: kMinInteractiveDimension,
|
||||
minHeight: kMinInteractiveDimension,
|
||||
),
|
||||
child: IconTheme.merge(
|
||||
data: IconThemeData(
|
||||
color: iconColor,
|
||||
@@ -2172,7 +2188,10 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
||||
widthFactor: 1.0,
|
||||
heightFactor: 1.0,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(minWidth: 48.0, minHeight: 48.0),
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: kMinInteractiveDimension,
|
||||
minHeight: kMinInteractiveDimension,
|
||||
),
|
||||
child: IconTheme.merge(
|
||||
data: IconThemeData(
|
||||
color: iconColor,
|
||||
@@ -2253,6 +2272,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
||||
input: widget.child,
|
||||
label: label,
|
||||
alignLabelWithHint: decoration.alignLabelWithHint,
|
||||
isDense: decoration.isDense,
|
||||
hint: hint,
|
||||
prefix: prefix,
|
||||
suffix: suffix,
|
||||
|
||||
@@ -509,12 +509,12 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 40.0));
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 12.0);
|
||||
expect(tester.getBottomLeft(find.text('text')).dy, 28.0);
|
||||
expect(tester.getTopLeft(find.text('hint')).dy, 12.0);
|
||||
expect(tester.getBottomLeft(find.text('hint')).dy, 28.0);
|
||||
expect(getBorderBottom(tester), 40.0);
|
||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension));
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 16.0);
|
||||
expect(tester.getBottomLeft(find.text('text')).dy, 32.0);
|
||||
expect(tester.getTopLeft(find.text('hint')).dy, 16.0);
|
||||
expect(tester.getBottomLeft(find.text('hint')).dy, 32.0);
|
||||
expect(getBorderBottom(tester), 48.0);
|
||||
expect(getBorderWeight(tester), 1.0);
|
||||
|
||||
expect(tester.getSize(find.text('hint')).width, tester.getSize(find.text('text')).width);
|
||||
@@ -1144,14 +1144,14 @@ void main() {
|
||||
// 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).
|
||||
|
||||
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('p')).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('p')).dy, 12.0);
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 16.0);
|
||||
expect(tester.getTopLeft(find.text('p')).dy, 16.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);
|
||||
|
||||
// layout is a row: [p text s]
|
||||
@@ -1179,18 +1179,18 @@ void main() {
|
||||
// 16 - input text (ahem font size 16dps)
|
||||
// 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('p')).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('p')).dy, 12.0);
|
||||
expect(tester.getTopLeft(find.text('s')).dy, 12.0);
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 16.0);
|
||||
expect(tester.getTopLeft(find.text('p')).dy, 16.0);
|
||||
expect(tester.getTopLeft(find.text('s')).dy, 16.0);
|
||||
expect(tester.getTopRight(find.text('s')).dx, 788.0);
|
||||
expect(tester.getSize(find.byType(Icon)).height, 24.0);
|
||||
|
||||
// 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]
|
||||
expect(tester.getTopLeft(find.byType(Icon)).dx, 0.0);
|
||||
@@ -1939,10 +1939,10 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 44.0));
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 13.0);
|
||||
expect(tester.getBottomLeft(find.text('text')).dy, 29.0);
|
||||
expect(getBorderBottom(tester), 44.0);
|
||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 15.0);
|
||||
expect(tester.getBottomLeft(find.text('text')).dy, 31.0);
|
||||
expect(getBorderBottom(tester), 48.0);
|
||||
expect(getBorderWeight(tester), 1.0);
|
||||
});
|
||||
|
||||
@@ -1960,10 +1960,10 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 44.0));
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 13.0);
|
||||
expect(tester.getBottomLeft(find.text('text')).dy, 29.0);
|
||||
expect(getBorderBottom(tester), 44.0);
|
||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension));
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 15.0);
|
||||
expect(tester.getBottomLeft(find.text('text')).dy, 31.0);
|
||||
expect(getBorderBottom(tester), 48.0);
|
||||
expect(getBorderWeight(tester), 1.0);
|
||||
});
|
||||
|
||||
@@ -2098,7 +2098,7 @@ void main() {
|
||||
|
||||
// Margin for text decoration is 12 when filled
|
||||
// (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;
|
||||
expect(tester.getRect(find.text('test')).right, dx - 12.0);
|
||||
});
|
||||
@@ -2118,7 +2118,7 @@ void main() {
|
||||
|
||||
// Margin for text decoration is 12 when filled and top left offset is (0, 0)
|
||||
// 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);
|
||||
});
|
||||
|
||||
@@ -2236,13 +2236,13 @@ void main() {
|
||||
// 16 - input text (ahem font size 16dps)
|
||||
// 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('p')).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('p')).dy, 12.0);
|
||||
expect(tester.getTopLeft(find.text('s')).dy, 12.0);
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 16.0);
|
||||
expect(tester.getTopLeft(find.text('p')).dy, 16.0);
|
||||
expect(tester.getTopLeft(find.text('s')).dy, 16.0);
|
||||
|
||||
// layout is a row: [s text p]
|
||||
expect(tester.getTopLeft(find.text('s')).dx, 12.0);
|
||||
@@ -2339,10 +2339,10 @@ void main() {
|
||||
// 16 - input text (ahem font size 16dps)
|
||||
// 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.getTopLeft(find.text('text')).dy, 12.0);
|
||||
expect(getBorderBottom(tester), 40.0);
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 16.0);
|
||||
expect(getBorderBottom(tester), kMinInteractiveDimension); // 40 bumped up to minimum.
|
||||
expect(getBorderWeight(tester), 1.0);
|
||||
}, skip: isBrowser);
|
||||
|
||||
@@ -2360,9 +2360,9 @@ void main() {
|
||||
// Overall height for this InputDecorator is 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.getTopLeft(find.text('text')).dy, 0.0);
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 16.0);
|
||||
expect(getOpacity(tester, 'hint'), 0.0);
|
||||
expect(getBorderWeight(tester), 0.0);
|
||||
|
||||
@@ -2378,11 +2378,11 @@ void main() {
|
||||
);
|
||||
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.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.getTopLeft(find.text('hint')).dy, 0.0);
|
||||
expect(tester.getTopLeft(find.text('hint')).dy, 16.0);
|
||||
expect(getBorderWeight(tester), 0.0);
|
||||
}, skip: isBrowser);
|
||||
|
||||
@@ -2418,13 +2418,13 @@ void main() {
|
||||
// 10 - label (ahem font size 10dps)
|
||||
// 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('label')).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('label')).dy, 17.75);
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 23.5);
|
||||
expect(tester.getTopLeft(find.text('hint')).dy, 24.75);
|
||||
expect(tester.getTopLeft(find.text('label')).dy, 19.0);
|
||||
expect(tester.getTopLeft(find.text('text')).dy, 24.75);
|
||||
}, skip: isBrowser);
|
||||
|
||||
testWidgets('InputDecorator with empty style overrides', (WidgetTester tester) async {
|
||||
|
||||
@@ -519,10 +519,10 @@ void main() {
|
||||
|
||||
// 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.
|
||||
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.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));
|
||||
// First tap moved the cursor.
|
||||
expect(
|
||||
@@ -530,7 +530,7 @@ void main() {
|
||||
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();
|
||||
|
||||
// Second tap selects the word around the cursor.
|
||||
@@ -566,10 +566,10 @@ void main() {
|
||||
|
||||
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.tapAt(textfieldStart + const Offset(150.0, 5.0));
|
||||
await tester.tapAt(textfieldStart + const Offset(150.0, 9.0));
|
||||
await tester.pump();
|
||||
|
||||
// Selected text shows 'COPY', and not 'PASTE', 'CUT', 'SELECT ALL'.
|
||||
@@ -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 {
|
||||
@@ -5523,7 +5523,7 @@ void main() {
|
||||
|
||||
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();
|
||||
|
||||
// We moved the cursor.
|
||||
@@ -5557,7 +5557,7 @@ void main() {
|
||||
|
||||
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();
|
||||
|
||||
// We moved the cursor.
|
||||
@@ -5592,9 +5592,9 @@ void main() {
|
||||
|
||||
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.tapAt(textfieldStart + const Offset(50.0, 5.0));
|
||||
await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
|
||||
await tester.pump();
|
||||
|
||||
// Plain collapsed selection.
|
||||
@@ -5631,17 +5631,17 @@ void main() {
|
||||
|
||||
// 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.
|
||||
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.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));
|
||||
// First tap moved the cursor.
|
||||
expect(
|
||||
controller.selection,
|
||||
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();
|
||||
|
||||
// Second tap selects the word around the cursor.
|
||||
@@ -5677,17 +5677,17 @@ void main() {
|
||||
|
||||
// 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.
|
||||
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.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));
|
||||
// First tap moved the cursor.
|
||||
expect(
|
||||
controller.selection,
|
||||
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();
|
||||
|
||||
// Second tap selects the word around the cursor.
|
||||
@@ -5896,10 +5896,10 @@ void main() {
|
||||
|
||||
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));
|
||||
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.
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
|
||||
@@ -5945,17 +5945,17 @@ void main() {
|
||||
|
||||
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));
|
||||
// First tap moved the cursor.
|
||||
expect(
|
||||
controller.selection,
|
||||
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.tapAt(textfieldStart + const Offset(100.0, 5.0));
|
||||
await tester.tapAt(textfieldStart + const Offset(100.0, 9.0));
|
||||
await tester.pump();
|
||||
|
||||
// Plain collapsed selection at the edge of first word. In iOS 12, the
|
||||
@@ -5993,7 +5993,7 @@ void main() {
|
||||
|
||||
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();
|
||||
|
||||
// Collapsed cursor for iOS long press.
|
||||
@@ -6027,7 +6027,7 @@ void main() {
|
||||
|
||||
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();
|
||||
|
||||
expect(
|
||||
@@ -6061,10 +6061,10 @@ void main() {
|
||||
|
||||
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.tapAt(textfieldStart + const Offset(50.0, 5.0));
|
||||
await tester.tapAt(textfieldStart + const Offset(50.0, 9.0));
|
||||
await tester.pump();
|
||||
|
||||
// We ended up moving the cursor to the edge of the same word and dismissed
|
||||
@@ -6101,7 +6101,7 @@ void main() {
|
||||
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
|
||||
|
||||
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));
|
||||
|
||||
// Long press on iOS shows collapsed selection cursor.
|
||||
@@ -6258,17 +6258,17 @@ void main() {
|
||||
|
||||
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));
|
||||
// First tap moved the cursor to the beginning of the second word.
|
||||
expect(
|
||||
controller.selection,
|
||||
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.longPressAt(textfieldStart + const Offset(100.0, 5.0));
|
||||
await tester.longPressAt(textfieldStart + const Offset(100.0, 9.0));
|
||||
await tester.pump();
|
||||
|
||||
// Plain collapsed selection at the exact tap position.
|
||||
@@ -6303,17 +6303,17 @@ void main() {
|
||||
|
||||
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.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));
|
||||
// First tap moved the cursor.
|
||||
expect(
|
||||
controller.selection,
|
||||
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();
|
||||
|
||||
// Double tap selection.
|
||||
@@ -6346,13 +6346,13 @@ void main() {
|
||||
|
||||
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));
|
||||
expect(
|
||||
controller.selection,
|
||||
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));
|
||||
expect(
|
||||
controller.selection,
|
||||
@@ -6361,14 +6361,14 @@ void main() {
|
||||
expect(find.byType(CupertinoButton), findsNWidgets(3));
|
||||
|
||||
// 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));
|
||||
// First tap moved the cursor.
|
||||
expect(
|
||||
controller.selection,
|
||||
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));
|
||||
expect(
|
||||
controller.selection,
|
||||
@@ -6376,14 +6376,14 @@ void main() {
|
||||
);
|
||||
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));
|
||||
// First tap moved the cursor.
|
||||
expect(
|
||||
controller.selection,
|
||||
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));
|
||||
expect(
|
||||
controller.selection,
|
||||
@@ -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;
|
||||
final TestGesture gesture = await tester.createGesture();
|
||||
@@ -6421,7 +6421,7 @@ void main() {
|
||||
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.
|
||||
expect(controller.selection, const TextSelection.collapsed(offset: -1));
|
||||
@@ -6449,7 +6449,7 @@ void main() {
|
||||
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
|
||||
|
||||
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();
|
||||
await gesture.downWithCustomEvent(
|
||||
offset,
|
||||
@@ -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.
|
||||
expect(
|
||||
controller.selection,
|
||||
@@ -6492,7 +6492,7 @@ void main() {
|
||||
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
|
||||
|
||||
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();
|
||||
await gesture.downWithCustomEvent(
|
||||
offset,
|
||||
@@ -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();
|
||||
// The event should fallback to a normal tap and move the cursor.
|
||||
// Single taps selects the edge of the word.
|
||||
@@ -6602,9 +6602,11 @@ void main() {
|
||||
|
||||
expect(
|
||||
tester.getSize(find.byType(TextField)),
|
||||
// This is the height of the decoration (24) plus the metrics from the default
|
||||
// TextStyle of the theme (16).
|
||||
const Size(800, 40),
|
||||
// The TextField will be as tall as the decoration (24) plus the metrics
|
||||
// from the default TextStyle of the theme (16), or 40 altogether.
|
||||
// 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() {
|
||||
tester.getSize(find.byType(TextField)),
|
||||
// Strut should inherit the TextStyle.fontSize by default and produce the
|
||||
// same height as if it were disabled.
|
||||
const Size(800, 44),
|
||||
const Size(800, kMinInteractiveDimension), // Because 44 < 48.
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
@@ -6649,7 +6651,7 @@ void main() {
|
||||
expect(
|
||||
tester.getSize(find.byType(TextField)),
|
||||
// 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() {
|
||||
|
||||
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 TextEditingController controller = TextEditingController();
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
theme: ThemeData(),
|
||||
@@ -7245,7 +7246,7 @@ void main() {
|
||||
controller: scrollController,
|
||||
children: <Widget>[
|
||||
Container(height: 579), // Push field almost off screen.
|
||||
TextField(controller: controller),
|
||||
const TextField(),
|
||||
Container(height: 1000),
|
||||
],
|
||||
),
|
||||
@@ -7255,12 +7256,62 @@ void main() {
|
||||
|
||||
// Tap the TextField to put the cursor into it and bring it into view.
|
||||
expect(scrollController.offset, 0.0);
|
||||
await tester.tap(find.byType(TextField));
|
||||
await tester.tapAt(tester.getTopLeft(find.byType(TextField)));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// The ListView has scrolled to keep the TextField and cursor handle
|
||||
// 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 {
|
||||
final TextEditingController controller1 = TextEditingController();
|
||||
|
||||
Reference in New Issue
Block a user