Unverified Commit d188a8ff authored by Hans Muller's avatar Hans Muller Committed by GitHub

Update InputDecorator et al (#13734)

parent c3366a65
......@@ -55,6 +55,7 @@ export 'src/material/icons.dart';
export 'src/material/ink_highlight.dart';
export 'src/material/ink_splash.dart';
export 'src/material/ink_well.dart';
export 'src/material/input_border.dart';
export 'src/material/input_decorator.dart';
export 'src/material/list_tile.dart';
export 'src/material/material.dart';
......
This diff is collapsed.
......@@ -9,6 +9,7 @@ import 'package:flutter/widgets.dart';
import 'feedback.dart';
import 'input_decorator.dart';
import 'material.dart';
import 'text_selection.dart';
import 'theme.dart';
......
......@@ -285,6 +285,7 @@ class _ShapeDecorationPainter extends BoxPainter {
final ShapeDecoration _decoration;
Rect _lastRect;
TextDirection _lastTextDirection;
Path _outerPath;
Path _innerPath;
Paint _interiorPaint;
......@@ -292,10 +293,11 @@ class _ShapeDecorationPainter extends BoxPainter {
List<Path> _shadowPaths;
List<Paint> _shadowPaints;
void _precache(Rect rect) {
void _precache(Rect rect, TextDirection textDirection) {
assert(rect != null);
if (rect == _lastRect)
if (rect == _lastRect && textDirection == _lastTextDirection)
return;
// We reach here in two cases:
// - the very first time we paint, in which case everything except _decoration is null
// - subsequent times, if the rect has changed, in which case we only need to update
......@@ -328,7 +330,9 @@ class _ShapeDecorationPainter extends BoxPainter {
_outerPath = _decoration.shape.getOuterPath(rect);
if (_decoration.image != null)
_innerPath = _decoration.shape.getInnerPath(rect);
_lastRect = rect;
_lastTextDirection = textDirection;
}
void _paintShadows(Canvas canvas) {
......@@ -362,10 +366,11 @@ class _ShapeDecorationPainter extends BoxPainter {
assert(configuration != null);
assert(configuration.size != null);
final Rect rect = offset & configuration.size;
_precache(rect);
final TextDirection textDirection = configuration.textDirection;
_precache(rect, textDirection);
_paintShadows(canvas);
_paintInterior(canvas);
_paintImage(canvas, configuration);
_decoration.shape.paint(canvas, rect);
_decoration.shape.paint(canvas, rect, textDirection: textDirection);
}
}
......@@ -104,6 +104,15 @@ Future<Null> skipPastScrollingAnimation(WidgetTester tester) async {
await tester.pump(const Duration(milliseconds: 200));
}
double getOpacity(WidgetTester tester, Finder finder) {
return tester.widget<Opacity>(
find.ancestor(
of: finder,
matching: find.byType(Opacity),
)
).opacity;
}
void main() {
final MockClipboard mockClipboard = new MockClipboard();
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
......@@ -1006,33 +1015,26 @@ void main() {
);
// Neither the prefix or the suffix should initially be visible, only the hint.
expect(find.text('Prefix'), findsNothing);
expect(find.text('Suffix'), findsNothing);
expect(find.text('Hint'), findsOneWidget);
expect(getOpacity(tester, find.text('Prefix')), 0.0);
expect(getOpacity(tester, find.text('Suffix')), 0.0);
expect(getOpacity(tester, find.text('Hint')), 1.0);
await tester.tap(find.byKey(secondKey));
await tester.pump();
await tester.pumpAndSettle();
// Focus the Input. The hint should display, but not the prefix and suffix.
expect(find.text('Prefix'), findsNothing);
expect(find.text('Suffix'), findsNothing);
expect(find.text('Hint'), findsOneWidget);
// Focus the Input. The hint, prefix, and suffix should appear
expect(getOpacity(tester, find.text('Prefix')), 1.0);
expect(getOpacity(tester, find.text('Suffix')), 1.0);
expect(getOpacity(tester, find.text('Hint')), 1.0);
// Enter some text, and the hint should disappear and the prefix and suffix
// should appear.
// should continue to be visible
await tester.enterText(find.byKey(secondKey), 'Hi');
await tester.pump();
await tester.pump(const Duration(seconds: 1));
await tester.pumpAndSettle();
expect(find.text('Prefix'), findsOneWidget);
expect(find.text('Suffix'), findsOneWidget);
// It's onstage, but animated to zero opacity.
expect(find.text('Hint'), findsOneWidget);
final Element target = tester.element(find.text('Hint'));
final Opacity opacity = target.ancestorWidgetOfExactType(Opacity);
expect(opacity, isNotNull);
expect(opacity.opacity, equals(0.0));
expect(getOpacity(tester, find.text('Prefix')), 1.0);
expect(getOpacity(tester, find.text('Suffix')), 1.0);
expect(getOpacity(tester, find.text('Hint')), 0.0);
// Check and make sure that the right styles were applied.
final Text prefixText = tester.widget(find.text('Prefix'));
......@@ -1077,27 +1079,25 @@ void main() {
),
);
// Not focused. The prefix should not display, but the label should.
expect(find.text('Prefix'), findsNothing);
expect(find.text('Suffix'), findsNothing);
// Not focused. The prefix and suffix should not appear, but the label should.
expect(getOpacity(tester, find.text('Prefix')), 0.0);
expect(getOpacity(tester, find.text('Suffix')), 0.0);
expect(find.text('Label'), findsOneWidget);
// Focus the input. The label, prefix, and suffix should appear.
await tester.tap(find.byKey(secondKey));
await tester.pump();
await tester.pumpAndSettle();
// Focus the input. The label should display, and also the prefix.
expect(find.text('Prefix'), findsOneWidget);
expect(find.text('Suffix'), findsOneWidget);
expect(getOpacity(tester, find.text('Prefix')), 1.0);
expect(getOpacity(tester, find.text('Suffix')), 1.0);
expect(find.text('Label'), findsOneWidget);
// Enter some text, and the label should stay and the prefix should
// remain.
// Enter some text. The label, prefix, and suffix should remain visible.
await tester.enterText(find.byKey(secondKey), 'Hi');
await tester.pump();
await tester.pump(const Duration(seconds: 1));
await tester.pumpAndSettle();
expect(find.text('Prefix'), findsOneWidget);
expect(find.text('Suffix'), findsOneWidget);
expect(getOpacity(tester, find.text('Prefix')), 1.0);
expect(getOpacity(tester, find.text('Suffix')), 1.0);
expect(find.text('Label'), findsOneWidget);
// Check and make sure that the right styles were applied.
......@@ -1148,21 +1148,25 @@ void main() {
expect(newPos.dy, lessThan(pos.dy));
});
testWidgets('No space between Input icon and text', (WidgetTester tester) async {
testWidgets('Icon is separated from input/label by 16+12', (WidgetTester tester) async {
await tester.pumpWidget(
overlay(
child: const TextField(
decoration: const InputDecoration(
icon: const Icon(Icons.phone),
labelText: 'label',
filled: true,
),
),
),
);
final double iconRight = tester.getTopRight(find.byType(Icon)).dx;
expect(iconRight, equals(tester.getTopLeft(find.text('label')).dx));
expect(iconRight, equals(tester.getTopLeft(find.byType(EditableText)).dx));
// Per https://material.io/guidelines/components/text-fields.html#text-fields-layout
// There's a 16 dps gap between the right edge of the icon and the text field's
// container, and the 12dps more padding between the left edge of the container
// and the left edge of the input and label.
expect(iconRight + 28.0, equals(tester.getTopLeft(find.text('label')).dx));
expect(iconRight + 28.0, equals(tester.getTopLeft(find.byType(EditableText)).dx));
});
testWidgets('Collapsed hint text placement', (WidgetTester tester) async {
......
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