InputDecorator should clip fill color to its border (#15795)
diff --git a/packages/flutter/lib/src/material/input_decorator.dart b/packages/flutter/lib/src/material/input_decorator.dart
index a5798dc..1038c97 100644
--- a/packages/flutter/lib/src/material/input_decorator.dart
+++ b/packages/flutter/lib/src/material/input_decorator.dart
@@ -68,6 +68,7 @@
this.gapAnimation,
this.gap,
this.textDirection,
+ this.fillColor,
}) : super(repaint: repaint);
final Animation<double> borderAnimation;
@@ -75,12 +76,25 @@
final Animation<double> gapAnimation;
final _InputBorderGap gap;
final TextDirection textDirection;
+ final Color fillColor;
@override
void paint(Canvas canvas, Size size) {
- border.evaluate(borderAnimation).paint(
+ final InputBorder borderValue = border.evaluate(borderAnimation);
+ final Rect canvasRect = Offset.zero & size;
+
+ if (fillColor.alpha > 0) {
+ canvas.drawPath(
+ borderValue.getOuterPath(canvasRect, textDirection: textDirection),
+ new Paint()
+ ..color = fillColor
+ ..style = PaintingStyle.fill,
+ );
+ }
+
+ borderValue.paint(
canvas,
- Offset.zero & size,
+ canvasRect,
gapStart: gap.start,
gapExtent: gap.extent,
gapPercentage: gapAnimation.value,
@@ -108,14 +122,17 @@
@required this.border,
@required this.gap,
@required this.gapAnimation,
+ @required this.fillColor,
this.child,
}) : assert(border != null),
assert(gap != null),
+ assert(fillColor != null),
super(key: key);
final InputBorder border;
final _InputBorderGap gap;
final Animation<double> gapAnimation;
+ final Color fillColor;
final Widget child;
@override
@@ -174,6 +191,7 @@
gapAnimation: widget.gapAnimation,
gap: widget.gap,
textDirection: Directionality.of(context),
+ fillColor: widget.fillColor,
),
child: widget.child,
);
@@ -1518,15 +1536,16 @@
),
);
- final Widget containerFill = new DecoratedBox(
- decoration: new BoxDecoration(color: _getFillColor(themeData)),
- );
- final Widget container = border == null ? containerFill : new _BorderContainer(
- border: border,
- gap: _borderGap,
- gapAnimation: _floatingLabelController.view,
- child: containerFill,
- );
+ final Widget container = border == null
+ ? new DecoratedBox(
+ decoration: new BoxDecoration(color: _getFillColor(themeData))
+ )
+ : new _BorderContainer(
+ border: border,
+ gap: _borderGap,
+ gapAnimation: _floatingLabelController.view,
+ fillColor: _getFillColor(themeData),
+ );
final TextStyle inlineLabelStyle = inlineStyle.merge(decoration.labelStyle);
final Widget label = decoration.labelText == null ? null : new _Shaker(
diff --git a/packages/flutter/test/material/input_decorator_test.dart b/packages/flutter/test/material/input_decorator_test.dart
index cbc5d5c..d088675 100644
--- a/packages/flutter/test/material/input_decorator_test.dart
+++ b/packages/flutter/test/material/input_decorator_test.dart
@@ -6,6 +6,8 @@
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
+import '../rendering/mock_canvas.dart';
+
Widget buildInputDecorator({
InputDecoration decoration: const InputDecoration(),
InputDecorationTheme inputDecorationTheme,
@@ -1188,4 +1190,44 @@
expect(decoration.fillColor, Colors.blue);
expect(decoration.border, const OutlineInputBorder());
});
+
+ testWidgets('InputDecorator fillColor is clipped by border', (WidgetTester tester) async {
+ // This is a regression test for https://github.com/flutter/flutter/issues/15742
+
+ await tester.pumpWidget(
+ buildInputDecorator(
+ // isEmpty: false (default)
+ // isFocused: false (default)
+ decoration: new InputDecoration(
+ filled: true,
+ fillColor: const Color(0xFF00FF00),
+ border: new OutlineInputBorder(
+ borderRadius: new BorderRadius.circular(12.0),
+ ),
+ ),
+ ),
+ );
+
+ final RenderBox box = tester.renderObject(find.byType(InputDecorator));
+
+ // Fill is the border's outer path, a rounded rectangle
+ expect(box, paints..path(
+ style: PaintingStyle.fill,
+ color: const Color(0xFF00FF00),
+ includes: <Offset>[const Offset(800.0/2.0, 56/2.0)],
+ excludes: <Offset>[
+ const Offset(1.0, 6.0), // outside the rounded corner, top left
+ const Offset(800.0 - 1.0, 6.0), // top right
+ const Offset(1.0, 56.0 - 6.0), // bottom left
+ const Offset(800 - 1.0, 56.0 - 6.0), // bottom right
+ ],
+ ));
+
+ // Border outline. The rrect is the -center- of the 1.0 stroked outline.
+ expect(box, paints..rrect(
+ style: PaintingStyle.stroke,
+ strokeWidth: 1.0,
+ rrect: new RRect.fromLTRBR(0.5, 0.5, 799.5, 55.5, const Radius.circular(11.5)),
+ ));
+ });
}