raj
raj

Reputation: 341

Flutter: How to enable only certain dates in DatePicker

I have an array with certain dates.

I want to disable these dates in the date picker and also change the color. How to do this?

Upvotes: 2

Views: 9302

Answers (2)

Siver Solutions
Siver Solutions

Reputation: 51

I encountered the same problem. After going back and forth, I did the following:

Created a list of specific dates:

static var unavailableDates = ["2020-08-14", "2020-08-20", "2020-08-13","2020-08-21","2020-08-23"];

Created an initial date variable:

static DateTime initialDate = DateTime.now();

formatted the initial date to get rid of the timestamp:

static DateFormat dateFormat = new DateFormat("yyyy-MM-dd");
String formattedDate = dateFormat.format(initialDate);

Put my unavailable dates in order:

unavailableDates.sort(((a, b) => a.compareTo(b)));

Added a way to verify the initial date does not fall on the disabled date. This jumps to the next available date. If you do not have something in place to verify unavailable date and initial date is not the same, you will get an exception:

for(var unavdate in unavailableDates){
    if (unavdate.compareTo(formattedDate) == 0) {
        formattedDate = unavdate;
        fromStringDate = DateTime.parse(formattedDate);
        initialDate = fromStringDate.add(new Duration(days: 1));
        formattedDate = dateFormat.format(initialDate);
    }
}

Created a day predicate function:

      bool setDayPredicate(DateTime val) {
          //this allows certain dates to be greyed out based on availability
          String Dates = dateFormat.format(val); //formatting passed in value
          return !unavailableDates.contains(Dates);
      }

Put it all together:

    date = await showDatePicker(
    context: context,
    initialDate: initialDate,
    firstDate: new DateTime.now(),
    lastDate: new DateTime.now().add(new Duration(days: 30)),
    selectableDayPredicate: setDayPredicate, });

Upvotes: 4

easeccy
easeccy

Reputation: 5086

You can use selectableDayPredicate property. For colors, you can change it by themes.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  DateTime selectedDate = DateTime(2020, 1, 14);

  // DatePicker will call this function on every day and expect
  // a bool output. If it's true, it will draw that day as "enabled"
  // and that day will be selectable and vice versa.
  bool _predicate(DateTime day) {
    if ((day.isAfter(DateTime(2020, 1, 5)) &&
        day.isBefore(DateTime(2020, 1, 9)))) {
      return true;
    }

    if ((day.isAfter(DateTime(2020, 1, 10)) &&
        day.isBefore(DateTime(2020, 1, 15)))) {
      return true;
    }
    if ((day.isAfter(DateTime(2020, 2, 5)) &&
        day.isBefore(DateTime(2020, 2, 17)))) {
      return true;
    }

    return false;
  }

  Future<void> _selectDate(BuildContext context) async {
    final DateTime picked = await showDatePicker(
        context: context,
        initialDate: selectedDate,
        selectableDayPredicate: _predicate,
        firstDate: DateTime(2019),
        lastDate: DateTime(2021),
        builder: (context, child) {
          return Theme(
            data: ThemeData(
                primaryColor: Colors.orangeAccent,
                disabledColor: Colors.brown,
                textTheme:
                    TextTheme(body1: TextStyle(color: Colors.blueAccent)),
                accentColor: Colors.yellow),
            child: child,
          );
        });
    if (picked != null && picked != selectedDate)
      setState(() {
        selectedDate = picked;
      });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Text("${selectedDate.toLocal()}".split(' ')[0]),
            SizedBox(
              height: 20.0,
            ),
            RaisedButton(
              onPressed: () => _selectDate(context),
              child: Text('Select date'),
            ),
          ],
        ),
      ),
    );
  }
}

Upvotes: 6

Related Questions