You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Description
This PR fixes SegmentedButton focus traversal.
# Before
When a focused segment (with no icon) is selected or unselected, the
focus moves to another segment.
[Capture vidéo du 2025-08-11
15-28-03.webm](https://github.com/user-attachments/assets/11c29194-6b96-4ea4-9245-dcbd36dc424f)
In this recording, tab key is used to set the focus on 'Month' segment,
then enter is used to select the segment. The focus move unexpectedly to
'Week' segment.
# After
When a focused segment (with no icon) is selected or unselected, the
focus stays on this same segment and the InkWell animations are
correctly painted.
[Capture vidéo du 2025-08-11
15-27-30.webm](https://github.com/user-attachments/assets/e09056d0-b572-462b-8ad8-c23eddcc4bfd)
<details><summary>Code sample for recordings</summary>
```dart
import 'package:flutter/material.dart';
/// Flutter code sample for [SegmentedButton].
void main() {
runApp(const SegmentedButtonApp());
}
class SegmentedButtonApp extends StatelessWidget {
const SegmentedButtonApp({super.key});
@OverRide
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(body: Center(child: SingleChoice())),
);
}
}
enum Calendar { day, week, month, year }
class SingleChoice extends StatefulWidget {
const SingleChoice({super.key});
@OverRide
State<SingleChoice> createState() => _SingleChoiceState();
}
class _SingleChoiceState extends State<SingleChoice> {
Calendar calendarView = Calendar.day;
@OverRide
Widget build(BuildContext context) {
return SegmentedButton<Calendar>(
segments: const <ButtonSegment<Calendar>>[
ButtonSegment<Calendar>(value: Calendar.day, label: Text('Day')),
ButtonSegment<Calendar>(value: Calendar.week, label: Text('Week')),
ButtonSegment<Calendar>(value: Calendar.month, label: Text('Month')),
ButtonSegment<Calendar>(value: Calendar.year, label: Text('Year')),
],
selected: <Calendar>{calendarView},
onSelectionChanged: (Set<Calendar> newSelection) {
setState(() {
// By default there is only a single segment that can be
// selected at one time, so its value is always the first
// item in the selected set.
calendarView = newSelection.first;
});
},
);
}
}
```
</details>
## Related Issue
Fixes [SegmentedButton keyboard navigation incorrectly moves focus on
click](flutter#161922)
## Implementation choice
The root of this issue is TextButton.icon which creates a different
widget tree depending on the icon.
See flutter#173944 for more context.
The proposed solution is to maintain the same widget tree when possible.
To do TextButton.icon is not used. This PR uses on TextButton and build
a child containing both the icon (when present) and the label.
In order to keep the same rendering as before, some internal logic from
TextButton.icon is duplicated.
## Tests
Adds 1 test.
Updates 1 test.
0 commit comments