Updated appearance of filled TextFields - added UnderlineInputBorder.borderRadius (#16272)
This commit is contained in:
@@ -116,7 +116,8 @@ class _NoInputBorder extends InputBorder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Draws a horizontal line at the bottom of an [InputDecorator]'s container.
|
||||
/// Draws a horizontal line at the bottom of an [InputDecorator]'s container and
|
||||
/// defines the container's shape.
|
||||
///
|
||||
/// The input decorator's "container" is the optionally filled area above the
|
||||
/// decorator's helper, error, and counter.
|
||||
@@ -133,16 +134,39 @@ class UnderlineInputBorder extends InputBorder {
|
||||
/// null). Applications typically do not specify a [borderSide] parameter
|
||||
/// because the input decorator substitutes its own, using [copyWith], based
|
||||
/// on the current theme and [InputDecorator.isFocused].
|
||||
///
|
||||
/// The [borderRadius] parameter defaults to a value where the top left
|
||||
/// and right corners have a circular radius of 4.0. The [borderRadius]
|
||||
/// parameter must not be null.
|
||||
const UnderlineInputBorder({
|
||||
BorderSide borderSide: BorderSide.none,
|
||||
}) : super(borderSide: borderSide);
|
||||
this.borderRadius: const BorderRadius.only(
|
||||
topLeft: const Radius.circular(4.0),
|
||||
topRight: const Radius.circular(4.0),
|
||||
),
|
||||
}) : assert(borderRadius != null),
|
||||
super(borderSide: borderSide);
|
||||
|
||||
/// The radii of the border's rounded rectangle corners.
|
||||
///
|
||||
/// When this border is used with a filled input decorator, see
|
||||
/// [InputDecoration.filled], the border radius defines the shape
|
||||
/// of the background fill as well as the bottom left and right
|
||||
/// edges of the underline itself.
|
||||
///
|
||||
/// By default the top right and top left corners have a circular radius
|
||||
/// of 4.0.
|
||||
final BorderRadius borderRadius;
|
||||
|
||||
@override
|
||||
bool get isOutline => false;
|
||||
|
||||
@override
|
||||
UnderlineInputBorder copyWith({ BorderSide borderSide }) {
|
||||
return new UnderlineInputBorder(borderSide: borderSide ?? this.borderSide);
|
||||
UnderlineInputBorder copyWith({ BorderSide borderSide, BorderRadius borderRadius }) {
|
||||
return new UnderlineInputBorder(
|
||||
borderSide: borderSide ?? this.borderSide,
|
||||
borderRadius: borderRadius ?? this.borderRadius,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -163,7 +187,7 @@ class UnderlineInputBorder extends InputBorder {
|
||||
|
||||
@override
|
||||
Path getOuterPath(Rect rect, { TextDirection textDirection }) {
|
||||
return new Path()..addRect(rect);
|
||||
return new Path()..addRRect(borderRadius.resolve(textDirection).toRRect(rect));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -197,6 +221,8 @@ class UnderlineInputBorder extends InputBorder {
|
||||
double gapPercentage: 0.0,
|
||||
TextDirection textDirection,
|
||||
}) {
|
||||
if (borderRadius.bottomLeft != Radius.zero || borderRadius.bottomRight != Radius.zero)
|
||||
canvas.clipPath(getOuterPath(rect, textDirection: textDirection));
|
||||
canvas.drawLine(rect.bottomLeft, rect.bottomRight, borderSide.toPaint());
|
||||
}
|
||||
|
||||
@@ -235,9 +261,10 @@ class OutlineInputBorder extends InputBorder {
|
||||
/// because the input decorator substitutes its own, using [copyWith], based
|
||||
/// on the current theme and [InputDecorator.isFocused].
|
||||
///
|
||||
/// If [borderRadius] is null (the default) then the border's corners
|
||||
/// are drawn with a radius of 4 logical pixels. The corner radii must be
|
||||
/// circular, i.e. their [Radius.x] and [Radius.y] values must be the same.
|
||||
/// The [borderRadius] parameter defaults to a value where all four
|
||||
/// corners have a circular radius of 4.0. The [borderRadius] parameter
|
||||
/// must not be null and the corner radii must be circular, i.e. their
|
||||
/// [Radius.x] and [Radius.y] values must be the same.
|
||||
const OutlineInputBorder({
|
||||
BorderSide borderSide: BorderSide.none,
|
||||
this.borderRadius: const BorderRadius.all(const Radius.circular(4.0)),
|
||||
|
||||
@@ -1217,7 +1217,7 @@ void main() {
|
||||
expect(decoration.border, const OutlineInputBorder());
|
||||
});
|
||||
|
||||
testWidgets('InputDecorator fillColor is clipped by border', (WidgetTester tester) async {
|
||||
testWidgets('InputDecorator OutlineInputBorder fillColor is clipped by border', (WidgetTester tester) async {
|
||||
// This is a regression test for https://github.com/flutter/flutter/issues/15742
|
||||
|
||||
await tester.pumpWidget(
|
||||
@@ -1256,4 +1256,36 @@ void main() {
|
||||
rrect: new RRect.fromLTRBR(0.5, 0.5, 799.5, 55.5, const Radius.circular(11.5)),
|
||||
));
|
||||
});
|
||||
|
||||
testWidgets('InputDecorator UnderlineInputBorder fillColor is clipped by border', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
// isEmpty: false (default)
|
||||
// isFocused: false (default)
|
||||
decoration: const InputDecoration(
|
||||
filled: true,
|
||||
fillColor: const Color(0xFF00FF00),
|
||||
border: const UnderlineInputBorder(
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomLeft: const Radius.circular(12.0),
|
||||
bottomRight: const Radius.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, 56.0 - 6.0), // bottom left
|
||||
const Offset(800 - 1.0, 56.0 - 6.0), // bottom right
|
||||
],
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user