Unverified Commit 3cd837fc authored by xubaolin's avatar xubaolin Committed by GitHub

Fix single ToggleButton border painting bugs (#73780)

parent 333dc5d8
...@@ -424,7 +424,9 @@ class ToggleButtons extends StatelessWidget { ...@@ -424,7 +424,9 @@ class ToggleButtons extends StatelessWidget {
?? toggleButtonsTheme.borderRadius ?? toggleButtonsTheme.borderRadius
?? BorderRadius.zero; ?? BorderRadius.zero;
if (direction == Axis.horizontal) { if (length == 1) {
return resultingBorderRadius;
} else if (direction == Axis.horizontal) {
if (_isFirstButton(index, length, textDirection)) { if (_isFirstButton(index, length, textDirection)) {
return BorderRadius.only( return BorderRadius.only(
topLeft: resultingBorderRadius.topLeft, topLeft: resultingBorderRadius.topLeft,
...@@ -466,7 +468,14 @@ class ToggleButtons extends StatelessWidget { ...@@ -466,7 +468,14 @@ class ToggleButtons extends StatelessWidget {
?? toggleButtonsTheme.borderWidth ?? toggleButtonsTheme.borderWidth
?? _defaultBorderWidth; ?? _defaultBorderWidth;
if (direction == Axis.horizontal) { if (length == 1) {
return BorderRadius.only(
topLeft: resultingBorderRadius.topLeft - Radius.circular(resultingBorderWidth / 2.0),
bottomLeft: resultingBorderRadius.bottomLeft - Radius.circular(resultingBorderWidth / 2.0),
topRight: resultingBorderRadius.topRight - Radius.circular(resultingBorderWidth / 2.0),
bottomRight: resultingBorderRadius.bottomRight - Radius.circular(resultingBorderWidth / 2.0),
);
} else if (direction == Axis.horizontal) {
if (_isFirstButton(index, length, textDirection)) { if (_isFirstButton(index, length, textDirection)) {
return BorderRadius.only( return BorderRadius.only(
topLeft: resultingBorderRadius.topLeft - Radius.circular(resultingBorderWidth / 2.0), topLeft: resultingBorderRadius.topLeft - Radius.circular(resultingBorderWidth / 2.0),
...@@ -1269,11 +1278,12 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1269,11 +1278,12 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
const double sweepAngle = math.pi / 2.0; const double sweepAngle = math.pi / 2.0;
final RRect rrect = RRect.fromRectAndCorners( final RRect rrect = RRect.fromRectAndCorners(
center, center,
topLeft: borderRadius.topLeft, topLeft: (borderRadius.topLeft.x * borderRadius.topLeft.y != 0.0) ? borderRadius.topLeft : Radius.zero,
topRight: borderRadius.topRight, topRight: (borderRadius.topRight.x * borderRadius.topRight.y != 0.0) ? borderRadius.topRight : Radius.zero,
bottomLeft: borderRadius.bottomLeft, bottomLeft: (borderRadius.bottomLeft.x * borderRadius.bottomLeft.y != 0.0) ? borderRadius.bottomLeft : Radius.zero,
bottomRight: borderRadius.bottomRight, bottomRight: (borderRadius.bottomRight.x * borderRadius.bottomRight.y != 0.0) ? borderRadius.bottomRight : Radius.zero,
).scaleRadii(); ).scaleRadii();
final Rect tlCorner = Rect.fromLTWH( final Rect tlCorner = Rect.fromLTWH(
rrect.left, rrect.left,
rrect.top, rrect.top,
...@@ -1299,8 +1309,25 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1299,8 +1309,25 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
rrect.brRadiusY * 2, rrect.brRadiusY * 2,
); );
final Paint leadingPaint = leadingBorderSide.toPaint();
// Only one button.
if (isFirstButton && isLastButton) {
final Path leadingPath = Path();
final double startX = (rrect.brRadiusX == 0.0) ? outer.right : rrect.right - rrect.brRadiusX;
leadingPath..moveTo(startX, rrect.bottom)
..lineTo(rrect.left + rrect.blRadiusX, rrect.bottom)
..addArc(blCorner, math.pi / 2.0, sweepAngle)
..lineTo(rrect.left, rrect.top + rrect.tlRadiusY)
..addArc(tlCorner, math.pi, sweepAngle)
..lineTo(rrect.right - rrect.trRadiusX, rrect.top)
..addArc(trCorner, math.pi * 3.0 / 2.0, sweepAngle)
..lineTo(rrect.right, rrect.bottom - rrect.brRadiusY)
..addArc(brCorner, 0, sweepAngle);
context.canvas.drawPath(leadingPath, leadingPaint);
return;
}
if (direction == Axis.horizontal) { if (direction == Axis.horizontal) {
final Paint leadingPaint = leadingBorderSide.toPaint();
switch (textDirection) { switch (textDirection) {
case TextDirection.ltr: case TextDirection.ltr:
if (isLastButton) { if (isLastButton) {
...@@ -1339,7 +1366,6 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1339,7 +1366,6 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
..lineTo(outer.right - rrect.trRadiusX, rrect.top) ..lineTo(outer.right - rrect.trRadiusX, rrect.top)
..moveTo(rrect.left + borderSide.width / 2.0 + rrect.tlRadiusX, rrect.bottom) ..moveTo(rrect.left + borderSide.width / 2.0 + rrect.tlRadiusX, rrect.bottom)
..lineTo(outer.right - rrect.trRadiusX, rrect.bottom); ..lineTo(outer.right - rrect.trRadiusX, rrect.bottom);
context.canvas.drawPath(horizontalPaths, horizontalPaint); context.canvas.drawPath(horizontalPaths, horizontalPaint);
} }
break; break;
...@@ -1385,14 +1411,12 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1385,14 +1411,12 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
break; break;
} }
} else { } else {
final Paint leadingPaint = leadingBorderSide.toPaint();
switch (verticalDirection) { switch (verticalDirection) {
case VerticalDirection.down: case VerticalDirection.down:
if (isLastButton) { if (isLastButton) {
final Path topPath = Path(); final Path topPath = Path();
topPath..moveTo(outer.left, outer.top + leadingBorderSide.width / 2) topPath..moveTo(outer.left, outer.top + leadingBorderSide.width / 2)
..lineTo(outer.right, outer.top + leadingBorderSide.width / 2); ..lineTo(outer.right, outer.top + leadingBorderSide.width / 2);
context.canvas.drawPath(topPath, leadingPaint); context.canvas.drawPath(topPath, leadingPaint);
final Paint endingPaint = trailingBorderSide.toPaint(); final Paint endingPaint = trailingBorderSide.toPaint();
...@@ -1403,7 +1427,6 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1403,7 +1427,6 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
..lineTo(rrect.right - rrect.blRadiusX, rrect.bottom) ..lineTo(rrect.right - rrect.blRadiusX, rrect.bottom)
..addArc(brCorner, math.pi / 2.0, -sweepAngle) ..addArc(brCorner, math.pi / 2.0, -sweepAngle)
..lineTo(rrect.right, rrect.top + leadingBorderSide.width / 2.0); ..lineTo(rrect.right, rrect.top + leadingBorderSide.width / 2.0);
context.canvas.drawPath(endingPath, endingPaint); context.canvas.drawPath(endingPath, endingPaint);
} else if (isFirstButton) { } else if (isFirstButton) {
final Path leadingPath = Path(); final Path leadingPath = Path();
...@@ -1413,7 +1436,6 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1413,7 +1436,6 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
..lineTo(rrect.right - rrect.trRadiusX, rrect.top) ..lineTo(rrect.right - rrect.trRadiusX, rrect.top)
..addArc(trCorner, math.pi * 3.0 / 2.0, sweepAngle) ..addArc(trCorner, math.pi * 3.0 / 2.0, sweepAngle)
..lineTo(rrect.right, outer.bottom); ..lineTo(rrect.right, outer.bottom);
context.canvas.drawPath(leadingPath, leadingPaint); context.canvas.drawPath(leadingPath, leadingPaint);
} else { } else {
final Path topPath = Path(); final Path topPath = Path();
...@@ -1427,7 +1449,6 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1427,7 +1449,6 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
..lineTo(rrect.left, outer.bottom) ..lineTo(rrect.left, outer.bottom)
..moveTo(rrect.right, outer.top + leadingBorderSide.width) ..moveTo(rrect.right, outer.top + leadingBorderSide.width)
..lineTo(rrect.right, outer.bottom); ..lineTo(rrect.right, outer.bottom);
context.canvas.drawPath(paths, paint); context.canvas.drawPath(paths, paint);
} }
break; break;
......
...@@ -891,13 +891,6 @@ void main() { ...@@ -891,13 +891,6 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// trailing side
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
strokeWidth: defaultBorderWidth,
)
// leading side, top and bottom
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12), color: theme.colorScheme.onSurface.withOpacity(0.12),
...@@ -925,13 +918,6 @@ void main() { ...@@ -925,13 +918,6 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// trailing side
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
strokeWidth: defaultBorderWidth,
)
// leading side, top and bottom
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12), color: theme.colorScheme.onSurface.withOpacity(0.12),
...@@ -958,13 +944,6 @@ void main() { ...@@ -958,13 +944,6 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// trailing side
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
strokeWidth: defaultBorderWidth,
)
// leading side, top and bottom
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12), color: theme.colorScheme.onSurface.withOpacity(0.12),
...@@ -1005,13 +984,6 @@ void main() { ...@@ -1005,13 +984,6 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// trailing side
..path(
style: PaintingStyle.stroke,
color: borderColor,
strokeWidth: customWidth,
)
// leading side, top and bottom
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: borderColor, color: borderColor,
...@@ -1041,13 +1013,6 @@ void main() { ...@@ -1041,13 +1013,6 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// trailing side
..path(
style: PaintingStyle.stroke,
color: selectedBorderColor,
strokeWidth: customWidth,
)
// leading side, top and bottom
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: selectedBorderColor, color: selectedBorderColor,
...@@ -1076,13 +1041,6 @@ void main() { ...@@ -1076,13 +1041,6 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// trailing side
..path(
style: PaintingStyle.stroke,
color: disabledBorderColor,
strokeWidth: customWidth,
)
// leading side, top and bottom
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: disabledBorderColor, color: disabledBorderColor,
...@@ -1510,6 +1468,80 @@ void main() { ...@@ -1510,6 +1468,80 @@ void main() {
}, },
); );
// Regression test for https://github.com/flutter/flutter/issues/73725
testWidgets('Border radius paint test when there is only one button', (WidgetTester tester) async {
final ThemeData theme = ThemeData();
await tester.pumpWidget(
Material(
child: boilerplate(
child: RepaintBoundary(
child: ToggleButtons(
borderRadius: const BorderRadius.all(Radius.circular(7.0)),
isSelected: const <bool>[true],
onPressed: (int index) {},
children: const <Widget>[
Text('First child'),
],
),
),
),
),
);
// The only button should be laid out at the center of the screen.
expect(tester.getCenter(find.text('First child')), const Offset(400.0, 300.0));
final List<RenderObject> toggleButtonRenderObject = tester.allRenderObjects.where((RenderObject object) {
return object.runtimeType.toString() == '_SelectToggleButtonRenderObject';
}).toSet().toList();
// The first button paints the left, top and right sides with a path.
expect(
toggleButtonRenderObject[0],
paints
// left side, top and right - enabled.
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
strokeWidth: _defaultBorderWidth,
),
);
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('toggle_buttons.oneButton.boardsPaint.png'),
);
});
testWidgets('Border radius paint test when Radius.x or Radius.y equal 0.0', (WidgetTester tester) async {
await tester.pumpWidget(
Material(
child: boilerplate(
child: RepaintBoundary(
child: ToggleButtons(
borderRadius: const BorderRadius.only(
topRight: Radius.elliptical(10, 0),
topLeft: Radius.elliptical(0, 10),
bottomRight: Radius.elliptical(0, 10),
bottomLeft: Radius.elliptical(10, 0),
),
isSelected: const <bool>[true],
onPressed: (int index) {},
children: const <Widget>[
Text('First child'),
],
),
),
),
),
);
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('toggle_buttons.oneButton.boardsPaint2.png'),
);
});
testWidgets('ToggleButtons implements debugFillProperties', (WidgetTester tester) async { testWidgets('ToggleButtons implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
......
...@@ -476,13 +476,6 @@ void main() { ...@@ -476,13 +476,6 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// trailing side
..path(
style: PaintingStyle.stroke,
color: borderColor,
strokeWidth: customWidth,
)
// leading side, top and bottom
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: borderColor, color: borderColor,
...@@ -516,13 +509,6 @@ void main() { ...@@ -516,13 +509,6 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// trailing side
..path(
style: PaintingStyle.stroke,
color: selectedBorderColor,
strokeWidth: customWidth,
)
// leading side, top and bottom
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: selectedBorderColor, color: selectedBorderColor,
...@@ -555,13 +541,6 @@ void main() { ...@@ -555,13 +541,6 @@ void main() {
expect( expect(
toggleButtonRenderObject, toggleButtonRenderObject,
paints paints
// trailing side
..path(
style: PaintingStyle.stroke,
color: disabledBorderColor,
strokeWidth: customWidth,
)
// leading side, top and bottom
..path( ..path(
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
color: disabledBorderColor, color: disabledBorderColor,
......
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