Category / Section
How to use multi colors for multi range selection in the Flutter date range picker (SfDateRangePicker)
4 mins read
In the Flutter date range picker, use multiple colors for multi-range selection by using the CustomPainter with cellBuilder.
STEP 1: In initState(), initialize the default values for picker.
DateRangePickerSelectionMode _selectionMode = DateRangePickerSelectionMode.multiRange; DateRangePickerController _controller = DateRangePickerController(); @override void initState() { _controller.view = DateRangePickerView.month; _controller.selectedDate = DateTime(2021, 9, 5); _controller.selectedRange = PickerDateRange(DateTime(2021, 9, 7), DateTime(2021, 9, 11)); _controller.selectedRanges = <PickerDateRange>[ PickerDateRange(DateTime.now().subtract(Duration(days: 4)), DateTime.now().add(Duration(days: 4))), PickerDateRange(DateTime.now().add(Duration(days: 11)), DateTime.now().add(Duration(days: 16))) ]; super.initState(); }
STEP 2: Set the startRangeSelectionColor, endRangeSelectionColor, rangeSelectionColor, selectionColor value as transparent. Then based on the cellBuilder update the cell with the custom widget.
body: SfDateRangePicker( controller: _controller, selectionMode: _selectionMode, startRangeSelectionColor: Colors.transparent, endRangeSelectionColor: Colors.transparent, rangeSelectionColor: Colors.transparent, selectionColor: Colors.transparent, cellBuilder: (BuildContext context, DateRangePickerCellDetails details) { if (_selectionMode == DateRangePickerSelectionMode.range) { return Container( child: CustomPaint( painter: RangeSelection(details.date, _controller), size: Size(details.bounds.width, details.bounds.height), )); } else if (_selectionMode == DateRangePickerSelectionMode.multiRange) { return Container( child: CustomPaint( painter: MultiRangeSelection(details.date, _controller), size: Size(details.bounds.width, details.bounds.height), )); } return Container( child: CustomPaint( painter: SingleSelection(details.date, _controller), size: Size(details.bounds.width, details.bounds.height), )); }, )
STEP 3: Then based on the selection handle select UI for different selection modes using CustomPainter through cellBuilder support, and here for multi-selection a different color has been used.
class MultiRangeSelection extends CustomPainter{ MultiRangeSelection(this.date, this.controller); final DateTime date; final DateRangePickerController controller; final TextPainter _textPainter = TextPainter(); bool isSameDate(DateTime start,DateTime end){ return start.year==end.year &&start.month==end.month && start.day==end.day; } @override void paint(Canvas canvas, Size size) { canvas.clipRect(Rect.fromLTWH(0, 0, size.width, size.height)); List<Color> selectedColors=<Color>[Colors.red,Colors.blue,Colors.green,Colors.yellow,Colors.pink]; List<PickerDateRange>? selectedRanges = controller.selectedRanges; bool isSelectedDate = false; for (int i = 0; i < selectedRanges!.length; i++) { Color selectedColor=selectedColors[i%selectedColors.length]; PickerDateRange range=selectedRanges[i]; DateTime startDate = range.startDate!; DateTime endDate = range.endDate ?? startDate; if (isSameDate(startDate,endDate)) { if (isSameDate(startDate,date)) { isSelectedDate = true; double x = size.width / 2; double y = size.height / 2; double radius = x > y ? y : x; radius = radius - 1; canvas.drawCircle(Offset(x, y), radius, Paint() ..color = selectedColor); } break; } else if (isSameDate(startDate,date)) { isSelectedDate = true; double x = size.width / 2; double y = size.height / 2; double radius = x > y ? y : x; radius = radius - 1; canvas.drawCircle(Offset(x, y), radius, Paint()..color = selectedColor); canvas.drawRect(Rect.fromLTRB(x, y - radius, size.width, y + radius), Paint()..color = selectedColor.withOpacity(0.25)); break; } else if (isSameDate(endDate,date)) { isSelectedDate = true; double x = size.width / 2; double y = size.height / 2; double radius = x > y ? y : x; radius = radius - 1; canvas.drawCircle(Offset(x, y), radius, Paint()..color = selectedColor); canvas.drawRect(Rect.fromLTRB(x, y - radius, 0, y + radius), Paint()..color = selectedColor.withOpacity(0.25)); break; } else if (startDate.isBefore(date) && endDate.isAfter(date)) { double x = size.width / 2; double y = size.height / 2; double radius = x > y ? y : x; radius = radius - 1; canvas.drawRect( Rect.fromLTRB(0, y - radius, size.width, y + radius), Paint() ..color = selectedColor.withOpacity(0.25)); break; } } final TextSpan dayTextSpan = TextSpan( text: date.day.toString(), style: TextStyle( color: isSelectedDate ? Colors.white : Colors.black, fontSize: 12)); _textPainter.text = dayTextSpan; _textPainter.textDirection = TextDirection.ltr; _textPainter.textAlign = TextAlign.center; _textPainter.maxLines = 1; _textPainter.layout(minWidth: size.width, maxWidth: size.width); double xPosition = (size.width - _textPainter.width) / 2; double yPosition = (size.height - _textPainter.height) / 2; _textPainter.paint(canvas, Offset(xPosition, yPosition)); } @override bool shouldRepaint(MultiRangeSelection oldDelegate) { return true; } } class SingleSelection extends CustomPainter { SingleSelection(this.date, this.controller); final DateTime date; final DateRangePickerController controller; final TextPainter _textPainter = TextPainter(); @override void paint(Canvas canvas, Size size) { canvas.clipRect(Rect.fromLTWH(0, 0, size.width, size.height)); DateTime selectedDate = controller.selectedDate!; bool isSelectedDate = false; if (controller.selectedDate != null) { if (selectedDate == date) { isSelectedDate = true; double x = size.width / 2; double y = size.height / 2; double radius = x > y ? y : x; radius = radius - 1; canvas.drawCircle(Offset(x, y), radius, Paint()..color = Colors.red); } } final TextSpan dayTextSpan = TextSpan( text: date.day.toString(), style: TextStyle( color: isSelectedDate ? Colors.white : Colors.black, fontSize: 12)); _textPainter.text = dayTextSpan; _textPainter.textDirection = TextDirection.ltr; _textPainter.textAlign = TextAlign.center; _textPainter.maxLines = 1; _textPainter.layout(minWidth: size.width, maxWidth: size.width); double xPosition = (size.width - _textPainter.width) / 2; double yPosition = (size.height - _textPainter.height) / 2; _textPainter.paint(canvas, Offset(xPosition, yPosition)); } @override bool shouldRepaint(SingleSelection oldDelegate) { return true; } } class RangeSelection extends CustomPainter { RangeSelection(this.date, this.controller); final DateTime date; final DateRangePickerController controller; final TextPainter _textPainter = TextPainter(); @override void paint(Canvas canvas, Size size) { canvas.clipRect(Rect.fromLTWH(0, 0, size.width, size.height)); DateTime startDate = controller.selectedRange!.startDate!; DateTime endDate = controller.selectedRange!.endDate ?? startDate; bool isSelectedDate = false; if (controller.selectedRange != null) { if (startDate == endDate) { if (startDate == date) { isSelectedDate = true; double x = size.width / 2; double y = size.height / 2; double radius = x > y ? y : x; radius = radius - 1; canvas.drawCircle(Offset(x, y), radius, Paint()..color = Colors.red); } } else if (startDate == date) { isSelectedDate = true; double x = size.width / 2; double y = size.height / 2; double radius = x > y ? y : x; radius = radius - 1; canvas.drawCircle(Offset(x, y), radius, Paint()..color = Colors.red); canvas.drawRect(Rect.fromLTRB(x, y - radius, size.width, y + radius), Paint()..color = Colors.red.withOpacity(0.25)); } else if (endDate == date) { isSelectedDate = true; double x = size.width / 2; double y = size.height / 2; double radius = x > y ? y : x; radius = radius - 1; canvas.drawCircle(Offset(x, y), radius, Paint()..color = Colors.red); canvas.drawRect(Rect.fromLTRB(x, y - radius, 0, y + radius), Paint()..color = Colors.red.withOpacity(0.25)); } else if (startDate.isBefore(date) && endDate.isAfter(date)) { double x = size.width / 2; double y = size.height / 2; double radius = x > y ? y : x; radius = radius - 1; canvas.drawRect(Rect.fromLTRB(0, y - radius, size.width, y + radius), Paint()..color = Colors.red.withOpacity(0.25)); } } final TextSpan dayTextSpan = TextSpan( text: date.day.toString(), style: TextStyle( color: isSelectedDate ? Colors.white : Colors.black, fontSize: 12)); _textPainter.text = dayTextSpan; _textPainter.textDirection = TextDirection.ltr; _textPainter.textAlign = TextAlign.center; _textPainter.maxLines = 1; _textPainter.layout(minWidth: size.width, maxWidth: size.width); double xPosition = (size.width - _textPainter.width) / 2; double yPosition = (size.height - _textPainter.height) / 2; _textPainter.paint(canvas, Offset(xPosition, yPosition)); } @override bool shouldRepaint(RangeSelection oldDelegate) { return true; } }