Fix OutlineInputBorder with BorderRadius.zero is distorted (#106849)
This commit is contained in:
@@ -439,44 +439,63 @@ class OutlineInputBorder extends InputBorder {
|
||||
scaledRRect.left,
|
||||
scaledRRect.bottom - scaledRRect.blRadiusY * 2.0,
|
||||
scaledRRect.blRadiusX * 2.0,
|
||||
scaledRRect.blRadiusX * 2.0,
|
||||
scaledRRect.blRadiusY * 2.0,
|
||||
);
|
||||
|
||||
// This assumes that the radius is circular (x and y radius are equal).
|
||||
// Currently, BorderRadius only supports circular radii.
|
||||
const double cornerArcSweep = math.pi / 2.0;
|
||||
final double tlCornerArcSweep = math.acos(
|
||||
clampDouble(1 - start / scaledRRect.tlRadiusX, 0.0, 1.0),
|
||||
);
|
||||
final Path path = Path();
|
||||
|
||||
final Path path = Path()
|
||||
..addArc(tlCorner, math.pi, tlCornerArcSweep);
|
||||
// Top left corner
|
||||
if (scaledRRect.tlRadius != Radius.zero) {
|
||||
final double tlCornerArcSweep = math.acos(clampDouble(1 - start / scaledRRect.tlRadiusX, 0.0, 1.0));
|
||||
path.addArc(tlCorner, math.pi, tlCornerArcSweep);
|
||||
} else {
|
||||
// Because the path is painted with Paint.strokeCap = StrokeCap.butt, horizontal coordinate is moved
|
||||
// to the left using borderSide.width / 2.
|
||||
path.moveTo(scaledRRect.left - borderSide.width / 2, scaledRRect.top);
|
||||
}
|
||||
|
||||
// Draw top border from top left corner to gap start.
|
||||
if (start > scaledRRect.tlRadiusX) {
|
||||
path.lineTo(scaledRRect.left + start, scaledRRect.top);
|
||||
}
|
||||
|
||||
// Draw top border from gap end to top right corner and draw top right corner.
|
||||
const double trCornerArcStart = (3 * math.pi) / 2.0;
|
||||
const double trCornerArcSweep = cornerArcSweep;
|
||||
if (start + extent < scaledRRect.width - scaledRRect.trRadiusX) {
|
||||
path.moveTo(scaledRRect.left + start + extent, scaledRRect.top);
|
||||
path.lineTo(scaledRRect.right - scaledRRect.trRadiusX, scaledRRect.top);
|
||||
path.addArc(trCorner, trCornerArcStart, trCornerArcSweep);
|
||||
if (scaledRRect.trRadius != Radius.zero) {
|
||||
path.addArc(trCorner, trCornerArcStart, trCornerArcSweep);
|
||||
}
|
||||
} else if (start + extent < scaledRRect.width) {
|
||||
final double dx = scaledRRect.width - (start + extent);
|
||||
final double sweep = math.asin(
|
||||
clampDouble(1 - dx / scaledRRect.trRadiusX, 0.0, 1.0),
|
||||
);
|
||||
final double sweep = math.asin(clampDouble(1 - dx / scaledRRect.trRadiusX, 0.0, 1.0));
|
||||
path.addArc(trCorner, trCornerArcStart + sweep, trCornerArcSweep - sweep);
|
||||
}
|
||||
|
||||
return path
|
||||
..moveTo(scaledRRect.right, scaledRRect.top + scaledRRect.trRadiusY)
|
||||
..lineTo(scaledRRect.right, scaledRRect.bottom - scaledRRect.brRadiusY)
|
||||
..addArc(brCorner, 0.0, cornerArcSweep)
|
||||
..lineTo(scaledRRect.left + scaledRRect.blRadiusX, scaledRRect.bottom)
|
||||
..addArc(blCorner, math.pi / 2.0, cornerArcSweep)
|
||||
..lineTo(scaledRRect.left, scaledRRect.top + scaledRRect.tlRadiusY);
|
||||
// Draw right border and bottom right corner.
|
||||
if (scaledRRect.brRadius != Radius.zero) {
|
||||
path.moveTo(scaledRRect.right, scaledRRect.top + scaledRRect.trRadiusY);
|
||||
}
|
||||
path.lineTo(scaledRRect.right, scaledRRect.bottom - scaledRRect.brRadiusY);
|
||||
if (scaledRRect.brRadius != Radius.zero) {
|
||||
path.addArc(brCorner, 0.0, cornerArcSweep);
|
||||
}
|
||||
|
||||
// Draw bottom border and bottom left corner.
|
||||
path.lineTo(scaledRRect.left + scaledRRect.blRadiusX, scaledRRect.bottom);
|
||||
if (scaledRRect.blRadius != Radius.zero) {
|
||||
path.addArc(blCorner, math.pi / 2.0, cornerArcSweep);
|
||||
}
|
||||
|
||||
// Draw left border
|
||||
path.lineTo(scaledRRect.left, scaledRRect.top + scaledRRect.tlRadiusY);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/// Draw a rounded rectangle around [rect] using [borderRadius].
|
||||
|
||||
@@ -4992,6 +4992,70 @@ void main() {
|
||||
);
|
||||
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/55317
|
||||
|
||||
testWidgets('OutlineInputBorder with BorderRadius.zero should draw a rectangular border', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/78855
|
||||
const String labelText = 'Flutter';
|
||||
|
||||
// Overall height for this InputDecorator is 56dps:
|
||||
// 12 - top padding
|
||||
// 12 - floating label (ahem font size 16dps * 0.75 = 12)
|
||||
// 4 - floating label / input text gap
|
||||
// 16 - input text (ahem font size 16dps)
|
||||
// 12 - bottom padding
|
||||
const double inputDecoratorHeight = 56.0;
|
||||
const double inputDecoratorWidth = 800.0;
|
||||
const double borderWidth = 4.0;
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
isFocused: true,
|
||||
decoration: const InputDecoration(
|
||||
filled: false,
|
||||
labelText: labelText,
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.zero,
|
||||
borderSide: BorderSide(width: borderWidth, color: Colors.red),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text(labelText), findsOneWidget);
|
||||
expect(findBorderPainter(), paints
|
||||
..save()
|
||||
..path(
|
||||
includes: const <Offset>[
|
||||
// Corner points in the middle of the border line should be in the path.
|
||||
// The path is not filled and borderWidth is 4.0 so Offset(2.0, 2.0) is in the path and Offset(1.0, 1.0) is not.
|
||||
// See Skia SkPath::contains method.
|
||||
|
||||
// Top-left
|
||||
Offset(borderWidth / 2, borderWidth / 2),
|
||||
// Top-right
|
||||
Offset(inputDecoratorWidth - 1 - borderWidth / 2, borderWidth / 2),
|
||||
// Bottom-left
|
||||
Offset(borderWidth / 2, inputDecoratorHeight - 1 - borderWidth / 2),
|
||||
// Bottom-right
|
||||
Offset(inputDecoratorWidth - 1 - borderWidth / 2, inputDecoratorHeight - 1 - borderWidth / 2),
|
||||
],
|
||||
excludes: const <Offset>[
|
||||
// The path is not filled and borderWidth is 4.0 so the path should not contains the corner points.
|
||||
// See Skia SkPath::contains method.
|
||||
|
||||
// Top-left
|
||||
Offset.zero,
|
||||
// // Top-right
|
||||
Offset(inputDecoratorWidth - 1, 0),
|
||||
// // Bottom-left
|
||||
Offset(0, inputDecoratorHeight - 1),
|
||||
// // Bottom-right
|
||||
Offset(inputDecoratorWidth - 1, inputDecoratorHeight - 1),
|
||||
],
|
||||
)
|
||||
..restore(),
|
||||
);
|
||||
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/55317
|
||||
|
||||
testWidgets('OutlineInputBorder radius carries over when lerping', (WidgetTester tester) async {
|
||||
// This is a regression test for https://github.com/flutter/flutter/issues/23982
|
||||
const Key key = Key('textField');
|
||||
@@ -5085,7 +5149,6 @@ void main() {
|
||||
expect(underlineInputBorder, isNot(const UnderlineInputBorder()));
|
||||
});
|
||||
|
||||
|
||||
test('InputBorder hashCodes', () {
|
||||
// OutlineInputBorder's hashCode is defined by the borderRadius, borderSide, & gapPadding
|
||||
const OutlineInputBorder outlineInputBorder = OutlineInputBorder(
|
||||
|
||||
Reference in New Issue
Block a user