Fix(Material): DateRangePicker ignores DatePickerTheme.dayShape (#181658)

<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->

This change fixes a problem where `showDateRangePicker` ignored the
`dayShape` property in `DatePickerThemeData`, leading to days always
rendering as circles regardless of the theme. This was caused by the
internal `_DayItem` widget using a hardcoded `BoxDecoration` regardless
of the theme configuration.

Fixes #181500

| Before | After |
| :---: | :---: |
| <img
src="https://github.com/user-attachments/assets/56a7c33e-ce91-4c30-8e62-ac0bceb1e3d3"
width="350"> | <img
src="https://github.com/user-attachments/assets/431c8ad2-0825-400a-8dd3-b264ec7430ce"
width="350"> |

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
This commit is contained in:
Akhil George 2026-02-19 04:30:57 +05:30 committed by GitHub
parent 96d292fa0a
commit e0e7a7d72d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 67 additions and 9 deletions

View File

@ -2855,7 +2855,7 @@ class _DayItemState extends State<_DayItem> {
final TextDirection textDirection = Directionality.of(context);
final Color highlightColor = widget.highlightColor;
BoxDecoration? decoration;
ShapeDecoration? decoration;
TextStyle? itemStyle = textTheme.bodyMedium;
T? effectiveValue<T>(T? Function(DatePickerThemeData? theme) getProperty) {
@ -2894,13 +2894,17 @@ class _DayItemState extends State<_DayItem> {
),
);
final OutlinedBorder dayShape =
resolve<OutlinedBorder?>((DatePickerThemeData? theme) => theme?.dayShape, states) ??
const CircleBorder();
_HighlightPainter? highlightPainter;
if (widget.isSelectedDayStart || widget.isSelectedDayEnd) {
// The selected start and end dates gets a circle background
// The selected start and end dates get a custom shaped background
// highlight, and a contrasting text color.
itemStyle = itemStyle?.apply(color: dayForegroundColor);
decoration = BoxDecoration(color: dayBackgroundColor, shape: BoxShape.circle);
decoration = ShapeDecoration(color: dayBackgroundColor, shape: dayShape);
if (widget.isRangeSelected && !widget.isOneDayRange) {
final _HighlightPainterStyle style = widget.isSelectedDayStart
@ -2925,13 +2929,13 @@ class _DayItemState extends State<_DayItem> {
} else if (widget.isDisabled) {
itemStyle = itemStyle?.apply(color: colorScheme.onSurface.withOpacity(0.38));
} else if (widget.isToday) {
// The current day gets a different text color and a circle stroke
// border.
// The current day gets a different text color and a custom shape border.
itemStyle = itemStyle?.apply(color: colorScheme.primary);
decoration = BoxDecoration(
border: Border.all(color: colorScheme.primary),
shape: BoxShape.circle,
final BorderSide todaySide = (datePickerTheme.todayBorder ?? defaults.todayBorder!).copyWith(
color: colorScheme.primary,
);
decoration = ShapeDecoration(shape: dayShape.copyWith(side: todaySide));
}
final String dayText = localizations.formatDecimal(widget.day.day);
@ -2969,7 +2973,8 @@ class _DayItemState extends State<_DayItem> {
dayWidget = InkResponse(
focusNode: widget.focusNode,
onTap: () => widget.onChanged(widget.day),
radius: _monthItemRowHeight / 2 + 4,
customBorder: dayShape,
containedInkWell: true,
statesController: _statesController,
overlayColor: dayOverlayColor,
onFocusChange: widget.onFocusChange,

View File

@ -2025,6 +2025,59 @@ void main() {
expect(tester.takeException(), null);
});
testWidgets('DateRangePicker respects DatePickerTheme.dayShape', (WidgetTester tester) async {
const OutlinedBorder customShape = BeveledRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(
datePickerTheme: const DatePickerThemeData(
dayShape: WidgetStatePropertyAll<OutlinedBorder>(customShape),
),
),
home: Material(
child: Builder(
builder: (BuildContext context) {
return ElevatedButton(
onPressed: () => showDateRangePicker(
context: context,
firstDate: DateTime(2023),
lastDate: DateTime(2024),
initialDateRange: DateTimeRange(
start: DateTime(2023, 1, 15),
end: DateTime(2023, 1, 20),
),
),
child: const Text('Open Picker'),
);
},
),
),
),
);
await tester.tap(find.text('Open Picker'));
await tester.pumpAndSettle();
final Finder selectedDayText = find.text('15');
final Finder dayContainerFinder = find
.ancestor(
of: selectedDayText,
matching: find.byWidgetPredicate((Widget widget) {
return widget is Container && widget.decoration is ShapeDecoration;
}),
)
.first;
final Container dayContainer = tester.widget<Container>(dayContainerFinder);
final decoration = dayContainer.decoration! as ShapeDecoration;
expect(decoration.shape, customShape);
});
}
class _RestorableDateRangePickerDialogTestWidget extends StatefulWidget {