Make a Calendar App with Flutter

What This App Does

A Calendar app serves a specific need in today's mobile-first world. Building one with Flutter means you ship to iOS, Android, and the web from a single codebase, cutting development time dramatically while keeping a native-quality experience.

Main Features

Feature Why It Matters
Month/Week/Day Views Toggle between month grid, weekly agenda, and daily timeline
Event Creation Tap a date to add an event with title, time, and colour-coded category
Recurrence Rules Support daily, weekly, monthly, and custom repeat patterns

How to Make a Calendar App with Flutter

Month/Week/Day Views

class CalendarScreen extends StatefulWidget {
  @override State createState() => _CalendarScreenState();
}

class _CalendarScreenState extends State {
  CalendarFormat _format = CalendarFormat.month;
  DateTime _selectedDay = DateTime.now();
  DateTime _focusedDay = DateTime.now();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TableCalendar(
          firstDay: DateTime(2020),
          lastDay: DateTime(2030),
          focusedDay: _focusedDay,
          selectedDayPredicate: (day) => isSameDay(_selectedDay, day),
          calendarFormat: _format,
          onFormatChanged: (format) => setState(() => _format = format),
          onDaySelected: (selected, focused) {
            setState(() {
              _selectedDay = selected;
              _focusedDay = focused;
            });
          },
        ),
        Expanded(
          child: EventList(date: _selectedDay),
        ),
      ],
    );
  }
}

Event Creation

class Event {
  final String title;
  final DateTime date;
  final TimeOfDay time;
  final Color color;
  final String? recurrenceRule;

  Event({required this.title, required this.date, required this.time,
    required this.color, this.recurrenceRule});
}

class CreateEventSheet extends StatefulWidget {
  final DateTime selectedDate;
  const CreateEventSheet({super.key, required this.selectedDate});
  @override State createState() => _CreateEventSheetState();
}

class _CreateEventSheetState extends State {
  final _formKey = GlobalKey();
  final _titleCtrl = TextEditingController();
  TimeOfDay _time = TimeOfDay.now();
  Color _color = Colors.blue;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(
        left: 16, right: 16, top: 16,
        bottom: MediaQuery.of(context).viewInsets.bottom + 16),
      child: Form(
        key: _formKey,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            TextFormField(
              controller: _titleCtrl,
              decoration: const InputDecoration(labelText: 'Event title'),
              validator: (v) => v?.isEmpty == true ? 'Required' : null,
            ),
            const SizedBox(height: 12),
            ColorPicker(selected: _color, onChanged: (c) => setState(() => _color = c)),
            const SizedBox(height: 12),
            ElevatedButton(
              onPressed: () {
                if (_formKey.currentState!.validate()) {
                  Navigator.pop(context, Event(
                    title: _titleCtrl.text, date: widget.selectedDate,
                    time: _time, color: _color,
                  ));
                }
              },
              child: const Text('Save Event'),
            ),
          ],
        ),
      ),
    );
  }
}

Recommended Libraries

Package Purpose
table_calendar Feature-rich calendar widget with multiple view formats
flutter_local_notifications Schedule reminders for events
drift Local database for event persistence and recurrence queries

UI & UX Suggestions

Use a blue primary, white cards, category colour dots (red=work, green=personal, purple=health) colour palette to match the app's purpose. Keep the navigation simple — a bottom nav bar or a single-scroll layout works best for this type of app. Make sure every interaction provides haptic or visual feedback so the app feels responsive and polished.