From e0e7a7d72db3fef30b221433e259e4e94a4d3aec Mon Sep 17 00:00:00 2001
From: Akhil George <74812392+akhil-ge0rge@users.noreply.github.com>
Date: Thu, 19 Feb 2026 04:30:57 +0530
Subject: [PATCH] Fix(Material): DateRangePicker ignores
DatePickerTheme.dayShape (#181658)
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 |
| :---: | :---: |
|
|
|
## 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.
---
.../flutter/lib/src/material/date_picker.dart | 23 ++++----
.../test/material/date_range_picker_test.dart | 53 +++++++++++++++++++
2 files changed, 67 insertions(+), 9 deletions(-)
diff --git a/packages/flutter/lib/src/material/date_picker.dart b/packages/flutter/lib/src/material/date_picker.dart
index f3729b8e7ed..dcb8ae5405a 100644
--- a/packages/flutter/lib/src/material/date_picker.dart
+++ b/packages/flutter/lib/src/material/date_picker.dart
@@ -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? Function(DatePickerThemeData? theme) getProperty) {
@@ -2894,13 +2894,17 @@ class _DayItemState extends State<_DayItem> {
),
);
+ final OutlinedBorder dayShape =
+ resolve((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,
diff --git a/packages/flutter/test/material/date_range_picker_test.dart b/packages/flutter/test/material/date_range_picker_test.dart
index 0d3733ef7a2..725ddc6f751 100644
--- a/packages/flutter/test/material/date_range_picker_test.dart
+++ b/packages/flutter/test/material/date_range_picker_test.dart
@@ -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(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(dayContainerFinder);
+ final decoration = dayContainer.decoration! as ShapeDecoration;
+
+ expect(decoration.shape, customShape);
+ });
}
class _RestorableDateRangePickerDialogTestWidget extends StatefulWidget {