Articles in this section
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;
  }
}

 

View sample in GitHub

Flutter date range picker multi color selection

 

 

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please  to leave a comment
Access denied
Access denied