-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Fix SegmentedButton border doesn't reflect states #172754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix SegmentedButton border doesn't reflect states #172754
Conversation
|
@QuncCccccc @victorsanni As you reviewed the initial PR (#172754), can you please review this one? |
| expect(find.byType(SegmentedButton<int>), paints..rrect(color: selectedColor)); | ||
| }); | ||
|
|
||
| testWidgets('SegmentedButton border sides respect disabled state', (WidgetTester tester) async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test passes on master, is this intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fd8c596 to
c93a982
Compare
|
@victorsanni Thanks for the review 🙏 |
QuncCccccc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thank you for continuing to finish this PR!
| // First segment is enabled, second is disabled. | ||
| segments: const <ButtonSegment<int>>[ | ||
| ButtonSegment<int>(value: 0, label: Text('0')), | ||
| ButtonSegment<int>(value: 1, label: Text('1'), enabled: false), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice test!
flutter/flutter@46b097a...c3279ca 2025-07-30 [email protected] Roll Skia from 00765f238077 to da5a6704f8a3 (1 revision) (flutter/flutter#172966) 2025-07-30 [email protected] Roll Skia from 62476cd444d2 to 00765f238077 (3 revisions) (flutter/flutter#172955) 2025-07-30 [email protected] Roll Skia from 34693354289f to 62476cd444d2 (1 revision) (flutter/flutter#172950) 2025-07-30 [email protected] Roll Skia from f72bd01a49b1 to 34693354289f (1 revision) (flutter/flutter#172946) 2025-07-30 [email protected] [a11y] add RangeSlider to a11y test app as additional use-case (flutter/flutter#172922) 2025-07-30 [email protected] Roll Skia from a42898e5d622 to f72bd01a49b1 (21 revisions) (flutter/flutter#172944) 2025-07-29 [email protected] Fix SegmentedButton border doesn't reflect states (flutter/flutter#172754) 2025-07-29 [email protected] Fix documentation for FlutterEngineRunTask (flutter/flutter#172889) 2025-07-29 [email protected] Roll Fuchsia Linux SDK from tK_PAaLeo0pUxi8hv... to bQVQlLssTxxLjoDU0... (flutter/flutter#172925) 2025-07-29 [email protected] fix(scrollbar): Update padding type to EdgeInsetsGeometry (flutter/flutter#172056) 2025-07-29 [email protected] Refactor Android platform view code in advance of enabling HCPP on existing PV widgets (behind a flag) (flutter/flutter#170553) 2025-07-29 [email protected] Roll Packages from 6b2e34e to ed235d1 (4 revisions) (flutter/flutter#172905) 2025-07-29 [email protected] Add package PR triage note (flutter/flutter#172898) 2025-07-29 [email protected] Roll Skia from 409e1c7ba09b to a42898e5d622 (29 revisions) (flutter/flutter#172906) 2025-07-29 [email protected] Made `android_gradle_print_build_variants_test.dart` more robust (flutter/flutter#172910) 2025-07-29 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Reland licenses cpp switch (#172671)" (flutter/flutter#172912) 2025-07-29 [email protected] Fix Gemini Code Assist for GitHub config yaml (flutter/flutter#172887) 2025-07-29 [email protected] Marks Linux_android_emu_unstable android_defines_test to be unflaky (flutter/flutter#171856) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…r#9699) flutter/flutter@46b097a...c3279ca 2025-07-30 [email protected] Roll Skia from 00765f238077 to da5a6704f8a3 (1 revision) (flutter/flutter#172966) 2025-07-30 [email protected] Roll Skia from 62476cd444d2 to 00765f238077 (3 revisions) (flutter/flutter#172955) 2025-07-30 [email protected] Roll Skia from 34693354289f to 62476cd444d2 (1 revision) (flutter/flutter#172950) 2025-07-30 [email protected] Roll Skia from f72bd01a49b1 to 34693354289f (1 revision) (flutter/flutter#172946) 2025-07-30 [email protected] [a11y] add RangeSlider to a11y test app as additional use-case (flutter/flutter#172922) 2025-07-30 [email protected] Roll Skia from a42898e5d622 to f72bd01a49b1 (21 revisions) (flutter/flutter#172944) 2025-07-29 [email protected] Fix SegmentedButton border doesn't reflect states (flutter/flutter#172754) 2025-07-29 [email protected] Fix documentation for FlutterEngineRunTask (flutter/flutter#172889) 2025-07-29 [email protected] Roll Fuchsia Linux SDK from tK_PAaLeo0pUxi8hv... to bQVQlLssTxxLjoDU0... (flutter/flutter#172925) 2025-07-29 [email protected] fix(scrollbar): Update padding type to EdgeInsetsGeometry (flutter/flutter#172056) 2025-07-29 [email protected] Refactor Android platform view code in advance of enabling HCPP on existing PV widgets (behind a flag) (flutter/flutter#170553) 2025-07-29 [email protected] Roll Packages from 6b2e34e to ed235d1 (4 revisions) (flutter/flutter#172905) 2025-07-29 [email protected] Add package PR triage note (flutter/flutter#172898) 2025-07-29 [email protected] Roll Skia from 409e1c7ba09b to a42898e5d622 (29 revisions) (flutter/flutter#172906) 2025-07-29 [email protected] Made `android_gradle_print_build_variants_test.dart` more robust (flutter/flutter#172910) 2025-07-29 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Reland licenses cpp switch (#172671)" (flutter/flutter#172912) 2025-07-29 [email protected] Fix Gemini Code Assist for GitHub config yaml (flutter/flutter#172887) 2025-07-29 [email protected] Marks Linux_android_emu_unstable android_defines_test to be unflaky (flutter/flutter#171856) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
## Description This PR fixes `SegmentedButton` border side not depending on the current state. It's based on one @TahaTesser 's great PR: see flutter#161942. 🙏 I updated some logic related to disabled border which led to Taha’s PR failing internal Google tests. I also added a test to verify the disabled border. <details><summary>Code sample for screenshots</summary> ```dart import 'package:flutter/material.dart'; void main() { runApp(const SegmentedButtonApp()); } enum Calendar { day, week, month, year } class SegmentedButtonApp extends StatefulWidget { const SegmentedButtonApp({super.key}); @OverRide State<SegmentedButtonApp> createState() => _SegmentedButtonAppState(); } class _SegmentedButtonAppState extends State<SegmentedButtonApp> { Calendar? calendarView; @OverRide Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( segmentedButtonTheme: SegmentedButtonThemeData( style: ButtonStyle( side: WidgetStateProperty.fromMap(<WidgetStatesConstraint, BorderSide?>{ WidgetState.disabled: const BorderSide(color: Colors.grey, width: 2), WidgetState.selected & WidgetState.hovered: const BorderSide( color: Colors.blue, width: 2, ), WidgetState.selected & WidgetState.focused: const BorderSide( color: Colors.pinkAccent, width: 2, ), WidgetState.hovered: const BorderSide(color: Colors.green, width: 2), WidgetState.focused: const BorderSide(color: Colors.purple, width: 2), WidgetState.any: const BorderSide(color: Colors.amber, width: 2), }), ), ), ), home: Scaffold( body: Center( child: SegmentedButton<Calendar>( segments: const <ButtonSegment<Calendar>>[ ButtonSegment<Calendar>( value: Calendar.day, label: Text('Day'), icon: Icon(Icons.calendar_view_day), enabled: false, ), ButtonSegment<Calendar>( value: Calendar.week, label: Text('Week'), icon: Icon(Icons.calendar_view_week), ), ButtonSegment<Calendar>( value: Calendar.month, label: Text('Month'), icon: Icon(Icons.calendar_view_month), ), ButtonSegment<Calendar>( value: Calendar.year, label: Text('Year'), icon: Icon(Icons.calendar_today), ), ], selected: <Calendar>{?calendarView}, emptySelectionAllowed: true, onSelectionChanged: (Set<Calendar> newSelection) { setState(() { calendarView = newSelection.isEmpty ? null : newSelection.first; }); }, ), ), floatingActionButton: FloatingActionButton(onPressed: () {}, child: const Icon(Icons.add)), ), ); } } ``` </details> # Before https://github.com/user-attachments/assets/1581f431-f87a-4af3-8ef6-f1f0d170e54a # After https://github.com/user-attachments/assets/156a8a64-3d9f-4323-9a1d-60624f5ac5d4 ## Related Issue Fixes [SegmentedButton does not set its MaterialState for side ](flutter#159884) ## Tests Adds 2 tests.
## Description This PR fixes `SegmentedButton` border side not depending on the current state. It's based on one @TahaTesser 's great PR: see flutter#161942. 🙏 I updated some logic related to disabled border which led to Taha’s PR failing internal Google tests. I also added a test to verify the disabled border. <details><summary>Code sample for screenshots</summary> ```dart import 'package:flutter/material.dart'; void main() { runApp(const SegmentedButtonApp()); } enum Calendar { day, week, month, year } class SegmentedButtonApp extends StatefulWidget { const SegmentedButtonApp({super.key}); @OverRide State<SegmentedButtonApp> createState() => _SegmentedButtonAppState(); } class _SegmentedButtonAppState extends State<SegmentedButtonApp> { Calendar? calendarView; @OverRide Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( segmentedButtonTheme: SegmentedButtonThemeData( style: ButtonStyle( side: WidgetStateProperty.fromMap(<WidgetStatesConstraint, BorderSide?>{ WidgetState.disabled: const BorderSide(color: Colors.grey, width: 2), WidgetState.selected & WidgetState.hovered: const BorderSide( color: Colors.blue, width: 2, ), WidgetState.selected & WidgetState.focused: const BorderSide( color: Colors.pinkAccent, width: 2, ), WidgetState.hovered: const BorderSide(color: Colors.green, width: 2), WidgetState.focused: const BorderSide(color: Colors.purple, width: 2), WidgetState.any: const BorderSide(color: Colors.amber, width: 2), }), ), ), ), home: Scaffold( body: Center( child: SegmentedButton<Calendar>( segments: const <ButtonSegment<Calendar>>[ ButtonSegment<Calendar>( value: Calendar.day, label: Text('Day'), icon: Icon(Icons.calendar_view_day), enabled: false, ), ButtonSegment<Calendar>( value: Calendar.week, label: Text('Week'), icon: Icon(Icons.calendar_view_week), ), ButtonSegment<Calendar>( value: Calendar.month, label: Text('Month'), icon: Icon(Icons.calendar_view_month), ), ButtonSegment<Calendar>( value: Calendar.year, label: Text('Year'), icon: Icon(Icons.calendar_today), ), ], selected: <Calendar>{?calendarView}, emptySelectionAllowed: true, onSelectionChanged: (Set<Calendar> newSelection) { setState(() { calendarView = newSelection.isEmpty ? null : newSelection.first; }); }, ), ), floatingActionButton: FloatingActionButton(onPressed: () {}, child: const Icon(Icons.add)), ), ); } } ``` </details> # Before https://github.com/user-attachments/assets/1581f431-f87a-4af3-8ef6-f1f0d170e54a # After https://github.com/user-attachments/assets/156a8a64-3d9f-4323-9a1d-60624f5ac5d4 ## Related Issue Fixes [SegmentedButton does not set its MaterialState for side ](flutter#159884) ## Tests Adds 2 tests.
## Description This PR fixes `SegmentedButton` border side not depending on the current state. It's based on one @TahaTesser 's great PR: see flutter#161942. 🙏 I updated some logic related to disabled border which led to Taha’s PR failing internal Google tests. I also added a test to verify the disabled border. <details><summary>Code sample for screenshots</summary> ```dart import 'package:flutter/material.dart'; void main() { runApp(const SegmentedButtonApp()); } enum Calendar { day, week, month, year } class SegmentedButtonApp extends StatefulWidget { const SegmentedButtonApp({super.key}); @OverRide State<SegmentedButtonApp> createState() => _SegmentedButtonAppState(); } class _SegmentedButtonAppState extends State<SegmentedButtonApp> { Calendar? calendarView; @OverRide Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( segmentedButtonTheme: SegmentedButtonThemeData( style: ButtonStyle( side: WidgetStateProperty.fromMap(<WidgetStatesConstraint, BorderSide?>{ WidgetState.disabled: const BorderSide(color: Colors.grey, width: 2), WidgetState.selected & WidgetState.hovered: const BorderSide( color: Colors.blue, width: 2, ), WidgetState.selected & WidgetState.focused: const BorderSide( color: Colors.pinkAccent, width: 2, ), WidgetState.hovered: const BorderSide(color: Colors.green, width: 2), WidgetState.focused: const BorderSide(color: Colors.purple, width: 2), WidgetState.any: const BorderSide(color: Colors.amber, width: 2), }), ), ), ), home: Scaffold( body: Center( child: SegmentedButton<Calendar>( segments: const <ButtonSegment<Calendar>>[ ButtonSegment<Calendar>( value: Calendar.day, label: Text('Day'), icon: Icon(Icons.calendar_view_day), enabled: false, ), ButtonSegment<Calendar>( value: Calendar.week, label: Text('Week'), icon: Icon(Icons.calendar_view_week), ), ButtonSegment<Calendar>( value: Calendar.month, label: Text('Month'), icon: Icon(Icons.calendar_view_month), ), ButtonSegment<Calendar>( value: Calendar.year, label: Text('Year'), icon: Icon(Icons.calendar_today), ), ], selected: <Calendar>{?calendarView}, emptySelectionAllowed: true, onSelectionChanged: (Set<Calendar> newSelection) { setState(() { calendarView = newSelection.isEmpty ? null : newSelection.first; }); }, ), ), floatingActionButton: FloatingActionButton(onPressed: () {}, child: const Icon(Icons.add)), ), ); } } ``` </details> # Before https://github.com/user-attachments/assets/1581f431-f87a-4af3-8ef6-f1f0d170e54a # After https://github.com/user-attachments/assets/156a8a64-3d9f-4323-9a1d-60624f5ac5d4 ## Related Issue Fixes [SegmentedButton does not set its MaterialState for side ](flutter#159884) ## Tests Adds 2 tests.
## Description This PR fixes `SegmentedButton` border side not depending on the current state. It's based on one @TahaTesser 's great PR: see flutter#161942. 🙏 I updated some logic related to disabled border which led to Taha’s PR failing internal Google tests. I also added a test to verify the disabled border. <details><summary>Code sample for screenshots</summary> ```dart import 'package:flutter/material.dart'; void main() { runApp(const SegmentedButtonApp()); } enum Calendar { day, week, month, year } class SegmentedButtonApp extends StatefulWidget { const SegmentedButtonApp({super.key}); @OverRide State<SegmentedButtonApp> createState() => _SegmentedButtonAppState(); } class _SegmentedButtonAppState extends State<SegmentedButtonApp> { Calendar? calendarView; @OverRide Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( segmentedButtonTheme: SegmentedButtonThemeData( style: ButtonStyle( side: WidgetStateProperty.fromMap(<WidgetStatesConstraint, BorderSide?>{ WidgetState.disabled: const BorderSide(color: Colors.grey, width: 2), WidgetState.selected & WidgetState.hovered: const BorderSide( color: Colors.blue, width: 2, ), WidgetState.selected & WidgetState.focused: const BorderSide( color: Colors.pinkAccent, width: 2, ), WidgetState.hovered: const BorderSide(color: Colors.green, width: 2), WidgetState.focused: const BorderSide(color: Colors.purple, width: 2), WidgetState.any: const BorderSide(color: Colors.amber, width: 2), }), ), ), ), home: Scaffold( body: Center( child: SegmentedButton<Calendar>( segments: const <ButtonSegment<Calendar>>[ ButtonSegment<Calendar>( value: Calendar.day, label: Text('Day'), icon: Icon(Icons.calendar_view_day), enabled: false, ), ButtonSegment<Calendar>( value: Calendar.week, label: Text('Week'), icon: Icon(Icons.calendar_view_week), ), ButtonSegment<Calendar>( value: Calendar.month, label: Text('Month'), icon: Icon(Icons.calendar_view_month), ), ButtonSegment<Calendar>( value: Calendar.year, label: Text('Year'), icon: Icon(Icons.calendar_today), ), ], selected: <Calendar>{?calendarView}, emptySelectionAllowed: true, onSelectionChanged: (Set<Calendar> newSelection) { setState(() { calendarView = newSelection.isEmpty ? null : newSelection.first; }); }, ), ), floatingActionButton: FloatingActionButton(onPressed: () {}, child: const Icon(Icons.add)), ), ); } } ``` </details> # Before https://github.com/user-attachments/assets/1581f431-f87a-4af3-8ef6-f1f0d170e54a # After https://github.com/user-attachments/assets/156a8a64-3d9f-4323-9a1d-60624f5ac5d4 ## Related Issue Fixes [SegmentedButton does not set its MaterialState for side ](flutter#159884) ## Tests Adds 2 tests.
Description
This PR fixes
SegmentedButtonborder side not depending on the current state.It's based on one @TahaTesser 's great PR: see #161942. 🙏
I updated some logic related to disabled border which led to Taha’s PR failing internal Google tests.
I also added a test to verify the disabled border.
Code sample for screenshots
Before
Screen.Recording.2025-07-25.at.10.40.40.mov
After
Screen.Recording.2025-07-25.at.10.39.33.mov
Related Issue
Fixes SegmentedButton does not set its MaterialState for side
Tests
Adds 2 tests.