Unverified Commit e4b78ffc authored by Justin McCandless's avatar Justin McCandless Committed by GitHub

TextField border gap padding improvement (#92940)

parent b460d0ee
...@@ -416,14 +416,15 @@ class OutlineInputBorder extends InputBorder { ...@@ -416,14 +416,15 @@ class OutlineInputBorder extends InputBorder {
scaledRRect.blRadiusX * 2.0, scaledRRect.blRadiusX * 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; const double cornerArcSweep = math.pi / 2.0;
final double tlCornerArcSweep = start < scaledRRect.tlRadiusX final double tlCornerArcSweep = math.acos(
? math.asin((start / scaledRRect.tlRadiusX).clamp(-1.0, 1.0)) (1 - start / scaledRRect.tlRadiusX).clamp(0.0, 1.0),
: math.pi / 2.0; );
final Path path = Path() final Path path = Path()
..addArc(tlCorner, math.pi, tlCornerArcSweep) ..addArc(tlCorner, math.pi, tlCornerArcSweep);
..moveTo(scaledRRect.left + scaledRRect.tlRadiusX, scaledRRect.top);
if (start > scaledRRect.tlRadiusX) if (start > scaledRRect.tlRadiusX)
path.lineTo(scaledRRect.left + start, scaledRRect.top); path.lineTo(scaledRRect.left + start, scaledRRect.top);
...@@ -431,13 +432,14 @@ class OutlineInputBorder extends InputBorder { ...@@ -431,13 +432,14 @@ class OutlineInputBorder extends InputBorder {
const double trCornerArcStart = (3 * math.pi) / 2.0; const double trCornerArcStart = (3 * math.pi) / 2.0;
const double trCornerArcSweep = cornerArcSweep; const double trCornerArcSweep = cornerArcSweep;
if (start + extent < scaledRRect.width - scaledRRect.trRadiusX) { if (start + extent < scaledRRect.width - scaledRRect.trRadiusX) {
path path.moveTo(scaledRRect.left + start + extent, scaledRRect.top);
..relativeMoveTo(extent, 0.0) path.lineTo(scaledRRect.right - scaledRRect.trRadiusX, scaledRRect.top);
..lineTo(scaledRRect.right - scaledRRect.trRadiusX, scaledRRect.top) path.addArc(trCorner, trCornerArcStart, trCornerArcSweep);
..addArc(trCorner, trCornerArcStart, trCornerArcSweep);
} else if (start + extent < scaledRRect.width) { } else if (start + extent < scaledRRect.width) {
final double dx = scaledRRect.width - (start + extent); final double dx = scaledRRect.width - (start + extent);
final double sweep = math.acos(dx / scaledRRect.trRadiusX); final double sweep = math.asin(
(1 - dx / scaledRRect.trRadiusX).clamp(0.0, 1.0),
);
path.addArc(trCorner, trCornerArcStart + sweep, trCornerArcSweep - sweep); path.addArc(trCorner, trCornerArcStart + sweep, trCornerArcSweep - sweep);
} }
......
...@@ -3838,6 +3838,53 @@ void main() { ...@@ -3838,6 +3838,53 @@ void main() {
); );
}); });
testWidgets(
'InputDecorator OutlineBorder focused label with icon',
(WidgetTester tester) async {
// This is a regression test for https://github.com/flutter/flutter/issues/82321
Widget buildFrame(TextDirection textDirection) {
return MaterialApp(
home: Scaffold(
body: Container(
padding: const EdgeInsets.all(16.0),
alignment: Alignment.center,
child: Directionality(
textDirection: textDirection,
child: RepaintBoundary(
child: InputDecorator(
isFocused: true,
isEmpty: true,
decoration: InputDecoration(
filled: true,
fillColor: const Color(0xFF00FF00),
labelText: 'label text',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
gapPadding: 0.0,
),
),
),
),
),
),
),
);
}
await tester.pumpWidget(buildFrame(TextDirection.ltr));
await expectLater(
find.byType(InputDecorator),
matchesGoldenFile('input_decorator.outline_label.ltr.png'),
);
await tester.pumpWidget(buildFrame(TextDirection.rtl));
await expectLater(
find.byType(InputDecorator),
matchesGoldenFile('input_decorator.outline_label.rtl.png'),
);
},
);
testWidgets( testWidgets(
'InputDecorator OutlineBorder focused label with icon', 'InputDecorator OutlineBorder focused label with icon',
(WidgetTester tester) async { (WidgetTester tester) async {
...@@ -4458,6 +4505,98 @@ void main() { ...@@ -4458,6 +4505,98 @@ void main() {
); );
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/55317 }, skip: isBrowser); // https://github.com/flutter/flutter/issues/55317
testWidgets('rounded OutlineInputBorder with zero padding just wraps the label', (WidgetTester tester) async {
// This is a regression test for https://github.com/flutter/flutter/issues/82321
const double borderRadius = 30.0;
const String labelText = 'label text';
// 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;
await tester.pumpWidget(
buildInputDecorator(
decoration: InputDecoration(
filled: true,
fillColor: const Color(0xFF00FF00),
labelText: labelText,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(borderRadius),
gapPadding: 0.0,
),
),
),
);
const double denominator = borderRadius * 2.0;
const double borderRadiusScaled = borderRadius / denominator * inputDecoratorHeight;
expect(find.text(labelText), findsOneWidget);
final Rect labelRect = tester.getRect(find.text(labelText));
expect(findBorderPainter(), paints
..save()
..path(
style: PaintingStyle.fill,
color: const Color(0xFF00FF00),
includes: <Offset>[
// The border should draw along the four edges of the
// InputDecorator.
// Top center
const Offset(inputDecoratorWidth / 2.0, 0.0),
// Bottom center
const Offset(inputDecoratorWidth / 2.0, inputDecoratorHeight),
// Left center
const Offset(0.0, inputDecoratorHeight / 2.0),
// Right center
const Offset(inputDecoratorWidth, inputDecoratorHeight / 2.0),
// The border path should contain points where each rounded corner
// ends.
// Bottom-right arc
const Offset(inputDecoratorWidth, inputDecoratorHeight - borderRadiusScaled),
const Offset(inputDecoratorWidth - borderRadiusScaled, inputDecoratorHeight),
// Top-right arc
const Offset(inputDecoratorWidth,0.0 + borderRadiusScaled),
const Offset(inputDecoratorWidth - borderRadiusScaled, 0.0),
// Bottom-left arc
const Offset(0.0, inputDecoratorHeight - borderRadiusScaled),
const Offset(0.0 + borderRadiusScaled, inputDecoratorHeight),
// Top-left arc
const Offset(0.0,0.0 + borderRadiusScaled),
const Offset(0.0 + borderRadiusScaled, 0.0),
// Gap edges
// gap start x = radius - radius * cos(arc sweep)
// gap start y = radius - radius * sin(arc sweep)
const Offset(39.49999999999999, 32.284366616798906),
Offset(39.49999999999999 + labelRect.width, 0.0),
],
excludes: const <Offset>[
// The border should not contain the corner points, since the border
// is rounded.
// Top-left
Offset.zero,
// Top-right
Offset(inputDecoratorWidth, 0.0),
// Bottom-left
Offset(0.0, inputDecoratorHeight),
// Bottom-right
Offset(inputDecoratorWidth, inputDecoratorHeight),
],
)
..restore(),
);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/55317
testWidgets('OutlineInputBorder radius carries over when lerping', (WidgetTester tester) async { testWidgets('OutlineInputBorder radius carries over when lerping', (WidgetTester tester) async {
// This is a regression test for https://github.com/flutter/flutter/issues/23982 // This is a regression test for https://github.com/flutter/flutter/issues/23982
const Key key = Key('textField'); const Key key = Key('textField');
......
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