diff --git a/packages/flutter/lib/src/material/segmented_button.dart b/packages/flutter/lib/src/material/segmented_button.dart index cbfcb2dfed2..0c0540f559b 100644 --- a/packages/flutter/lib/src/material/segmented_button.dart +++ b/packages/flutter/lib/src/material/segmented_button.dart @@ -895,12 +895,11 @@ class _RenderSegmentedButton extends RenderBox with Path? enabledClipPath; Path? disabledClipPath; - context.canvas..save()..clipPath(borderClipPath); while (child != null) { final _SegmentedButtonContainerBoxParentData childParentData = child.parentData! as _SegmentedButtonContainerBoxParentData; final Rect childRect = childParentData.surroundingRect!.outerRect.shift(offset); - context.canvas..save()..clipRect(childRect); + context.canvas..save()..clipPath(borderClipPath); context.paintChild(child, childParentData.offset + offset); context.canvas.restore(); @@ -935,8 +934,8 @@ class _RenderSegmentedButton extends RenderBox with final BorderSide divider = segments[index - 1].enabled || segments[index].enabled ? enabledBorder.side.copyWith(strokeAlign: 0.0) : disabledBorder.side.copyWith(strokeAlign: 0.0); - final Offset top = Offset(dividerPos, childRect.top); - final Offset bottom = Offset(dividerPos, childRect.bottom); + final Offset top = Offset(dividerPos, borderRect.top); + final Offset bottom = Offset(dividerPos, borderRect.bottom); context.canvas.drawLine(top, bottom, divider.toPaint()); } @@ -944,7 +943,6 @@ class _RenderSegmentedButton extends RenderBox with child = childAfter(child); index += 1; } - context.canvas.restore(); // Paint the outer border for both disabled and enabled clip rect if needed. if (disabledClipPath == null) { diff --git a/packages/flutter/test/material/segmented_button_test.dart b/packages/flutter/test/material/segmented_button_test.dart index c4a2f2bcd06..29ae55098e0 100644 --- a/packages/flutter/test/material/segmented_button_test.dart +++ b/packages/flutter/test/material/segmented_button_test.dart @@ -1045,6 +1045,79 @@ void main() { await tester.pumpAndSettle(); expect(getOverlayColor(tester), paints..rect(color: overlayColor)); }); + + // This is a regression test for https://github.com/flutter/flutter/issues/144990. + testWidgets('SegmentedButton clips border path when drawing segments', (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: Center( + child: SegmentedButton( + segments: const >[ + ButtonSegment( + value: 0, + label: Text('Option 1'), + ), + ButtonSegment( + value: 1, + label: Text('Option 2'), + ), + ], + onSelectionChanged: (Set selected) {}, + selected: const {0}, + ), + ), + ), + ), + ); + + expect( + find.byType(SegmentedButton), + paints + ..save() + ..clipPath() // Clip the border. + ..path(color: const Color(0xffe8def8)) // Draw segment 0. + ..save() + ..clipPath() // Clip the border. + ..path(color: const Color(0x00000000)), // Draw segment 1. + ); + }); + + // This is a regression test for https://github.com/flutter/flutter/issues/144990. + testWidgets('SegmentedButton dividers matches border rect size', (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: Center( + child: SegmentedButton( + segments: const >[ + ButtonSegment( + value: 0, + label: Text('Option 1'), + ), + ButtonSegment( + value: 1, + label: Text('Option 2'), + ), + ], + onSelectionChanged: (Set selected) {}, + selected: const {0}, + ), + ), + ), + ), + ); + + const double tapTargetSize = 48.0; + expect( + find.byType(SegmentedButton), + paints + ..line( + p1: const Offset(166.8000030517578, 4.0), + p2: const Offset(166.8000030517578, tapTargetSize - 4.0), + ), + ); + }); } Set enabled = const {};