scrollable_calender 0.0.3
scrollable_calender: ^0.0.3 copied to clipboard
A beautiful scrollable date picker for Flutter with customizable themes, smooth animations, and intuitive UX for date selection in mobile apps.
// ignore_for_file: library_private_types_in_public_api, deprecated_member_use
import 'package:flutter/material.dart';
import 'package:scrollable_calender/kest_scrollable_calender.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Kest Scrollable Calendar Example',
theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
home: const CalendarExamplePage(),
);
}
}
class CalendarExamplePage extends StatefulWidget {
const CalendarExamplePage({super.key});
@override
_CalendarExamplePageState createState() => _CalendarExamplePageState();
}
class _CalendarExamplePageState extends State<CalendarExamplePage> {
String selectedDate = "No date selected";
String selectedMonthYear = "No month/year selected";
String formDate = "";
bool isDarkMode = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Calendar Package Examples'),
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
actions: [
IconButton(
icon: Icon(isDarkMode ? Icons.light_mode : Icons.dark_mode),
onPressed: () {
setState(() {
isDarkMode = !isDarkMode;
});
},
tooltip:
isDarkMode ? 'Switch to Light Mode' : 'Switch to Dark Mode',
),
],
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Kest Scrollable Calendar Package',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blue[800],
),
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
'Two ways to use the calendar picker',
style: TextStyle(fontSize: 16, color: Colors.grey[600]),
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
// Theme Toggle Section
_buildSection(
title: '🎨 Theme Demonstration',
description:
'Toggle between light and dark themes to see the calendar adapt',
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey[100],
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: isDarkMode ? Colors.grey[600]! : Colors.grey[300]!,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Current Theme:',
style: TextStyle(
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black87,
),
),
const SizedBox(height: 4),
Text(
isDarkMode ? 'Dark Mode' : 'Light Mode',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: isDarkMode
? Colors.blue[300]
: Colors.blue[700],
),
),
],
),
ElevatedButton.icon(
onPressed: () {
setState(() {
isDarkMode = !isDarkMode;
});
},
icon:
Icon(isDarkMode ? Icons.light_mode : Icons.dark_mode),
label: Text(isDarkMode ? 'Light' : 'Dark'),
style: ElevatedButton.styleFrom(
backgroundColor:
isDarkMode ? Colors.orange : Colors.indigo,
foregroundColor: Colors.white,
),
),
],
),
),
),
const SizedBox(height: 24),
// Section 1: TextForm Field Version
_buildSection(
title: '1. TextForm Field Version',
description: 'Traditional form field that shows selected date',
child: Column(
children: [
CustomDateSelector(
label: "Birth Date",
theme:
isDarkMode ? CalendarTheme.dark : CalendarTheme.light,
onDateSelected: (year, month, day) {
setState(() {
formDate = "$day/$month/$year";
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Form field date selected: $day/$month/$year',
),
backgroundColor: Colors.green,
),
);
},
),
const SizedBox(height: 16),
if (formDate.isNotEmpty)
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.green[50],
border: Border.all(color: Colors.green[200]!),
borderRadius: BorderRadius.circular(8),
),
child: Text(
'Form field selected: $formDate',
style: TextStyle(
color: Colors.green[800],
fontWeight: FontWeight.w500,
),
),
),
],
),
),
const SizedBox(height: 24),
// Section 2: Standalone Method Version - Full Date
_buildSection(
title: '2. Standalone Method - Full Date Picker',
description: 'Call calendar from any widget as bottom sheet',
child: Column(
children: [
ElevatedButton.icon(
onPressed: () {
CalendarBottomSheet.showDatePicker(
context,
title: "Select Date",
theme: CalendarTheme.light.copyWith(
backgroundColor:
isDarkMode ? Colors.grey[800] : Colors.grey[100],
primaryColor:
isDarkMode ? Colors.white : Colors.black,
textColor: isDarkMode ? Colors.white : Colors.black87,
selectedColor:
isDarkMode ? Colors.blue[300] : Colors.blue[700],
dividerColor:
isDarkMode ? Colors.grey[600] : Colors.grey[300],
buttonColor:
isDarkMode ? Colors.orange : Colors.indigo,
buttonTextColor: Colors.white,
titleColor:
isDarkMode ? Colors.blue[300] : Colors.blue[700],
handleColor:
isDarkMode ? Colors.orange : Colors.indigo,
),
onDateSelected: (year, month, day) {
setState(() {
selectedDate = "$day/$month/$year";
});
},
);
},
icon: const Icon(Icons.calendar_today),
label: const Text('Show Date Picker'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
),
),
const SizedBox(height: 16),
if (selectedDate != "No date selected")
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.blue[50],
border: Border.all(color: Colors.blue[200]!),
borderRadius: BorderRadius.circular(8),
),
child: Text(
'Selected date: $selectedDate',
style: TextStyle(
color: Colors.blue[800],
fontWeight: FontWeight.w500,
),
),
),
],
),
),
const SizedBox(height: 24),
// Section 3: Standalone Method Version - Month/Year Only
_buildSection(
title: '3. Standalone Method - Month/Year Picker',
description: 'Month and year selection only (no day)',
child: Column(
children: [
ElevatedButton.icon(
onPressed: () {
CalendarBottomSheet.showMonthYearPicker(
context,
title: "Select Month/Year",
theme: isDarkMode
? CalendarTheme.dark
: CalendarTheme.light,
onDateSelected: (year, month, day) {
setState(() {
selectedMonthYear = "$month/$year";
});
},
);
},
icon: const Icon(Icons.calendar_month),
label: const Text('Show Month/Year Picker'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.purple,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
),
),
const SizedBox(height: 16),
if (selectedMonthYear != "No month/year selected")
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.purple[50],
border: Border.all(color: Colors.purple[200]!),
borderRadius: BorderRadius.circular(8),
),
child: Text(
'Selected month/year: $selectedMonthYear',
style: TextStyle(
color: Colors.purple[800],
fontWeight: FontWeight.w500,
),
),
),
],
),
),
const SizedBox(height: 24),
// Section 4: Dropdown Example
_buildSection(
title: '4. Dropdown Integration',
description: 'Trigger calendar from dropdown menu',
child: DropdownButtonFormField<String>(
decoration: const InputDecoration(
labelText: 'Choose Action',
border: OutlineInputBorder(),
),
hint: const Text('Select an option'),
items: const [
DropdownMenuItem(
value: 'full_date',
child: Text('Pick Full Date'),
),
DropdownMenuItem(
value: 'month_year',
child: Text('Pick Month/Year'),
),
],
onChanged: (value) {
if (value == 'full_date') {
CalendarBottomSheet.showDatePicker(
context,
theme:
isDarkMode ? CalendarTheme.dark : CalendarTheme.light,
onDateSelected: (year, month, day) {
setState(() {
selectedDate = "$day/$month/$year";
});
},
);
} else if (value == 'month_year') {
CalendarBottomSheet.showMonthYearPicker(
context,
theme:
isDarkMode ? CalendarTheme.dark : CalendarTheme.light,
onDateSelected: (year, month, day) {
setState(() {
selectedMonthYear = "$month/$year";
});
},
);
}
},
),
),
const SizedBox(height: 24),
// Section 5: Custom Parameters
_buildSection(
title: '5. Custom Parameters',
description: 'Using custom maxYear and type parameters',
child: ElevatedButton.icon(
onPressed: () {
CalendarBottomSheet.showDatePicker(
context,
title: "Select Future Date (up to 2030)",
maxYear: 2030,
type: "1",
theme:
isDarkMode ? CalendarTheme.dark : CalendarTheme.light,
onDateSelected: (year, month, day) {
setState(() {
selectedDate = "$day/$month/$year";
});
},
);
},
icon: const Icon(Icons.date_range),
label: const Text('Custom Date Picker'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.orange,
foregroundColor: Colors.white,
padding:
const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
),
),
),
const SizedBox(height: 24),
// Section 6: Custom Button Text
_buildSection(
title: '6. Custom Button Text',
description: 'Change the button text to match your app',
child: ElevatedButton.icon(
onPressed: () {
CalendarBottomSheet.showDatePicker(
context,
title: "Choose Your Date",
buttonText: "Confirm Selection",
theme:
isDarkMode ? CalendarTheme.dark : CalendarTheme.light,
onDateSelected: (year, month, day) {
setState(() {
selectedDate = "$day/$month/$year";
});
},
);
},
icon: const Icon(Icons.edit),
label: const Text('Custom Button Text'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.teal,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
),
),
),
const SizedBox(height: 24),
// Section 7: Custom Button Widget
_buildSection(
title: '7. Custom Button Widget',
description: 'Provide your own completely custom button',
child: ElevatedButton.icon(
onPressed: () {
CalendarBottomSheet.showDatePicker(
context,
title: "Select Date",
theme:
isDarkMode ? CalendarTheme.dark : CalendarTheme.light,
customButton: Container(
width: double.infinity,
height: 50,
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Colors.purple, Colors.pink],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(25),
boxShadow: [
BoxShadow(
color: Colors.purple.withOpacity(0.3),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(25),
onTap: () {
// Handle date selection
Navigator.of(context).pop();
},
child: const Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.check_circle,
color: Colors.white,
size: 20,
),
SizedBox(width: 8),
Text(
'Done',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
),
),
onDateSelected: (year, month, day) {
setState(() {
selectedDate = "$day/$month/$year";
});
},
);
},
icon: const Icon(Icons.gradient),
label: const Text('Custom Button Widget'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.deepPurple,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
),
),
),
const SizedBox(height: 32),
],
),
),
);
}
Widget _buildSection({
required String title,
required String description,
required Widget child,
}) {
return Card(
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.grey[800],
),
),
const SizedBox(height: 4),
Text(
description,
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
),
const SizedBox(height: 16),
child,
],
),
),
);
}
}