omni_calendar_view 1.0.2
omni_calendar_view: ^1.0.2 copied to clipboard
A pure Flutter calendar widget with powerful customization, supporting Gregorian and Lunar calendars, single date and date range selection. No third-party dependencies.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:omni_calendar_view/omni_calendar_view.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Omni Calendar Example',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: const ExamplePage(),
);
}
}
class ExamplePage extends StatefulWidget {
const ExamplePage({super.key});
@override
State<ExamplePage> createState() => _ExamplePageState();
}
class _ExamplePageState extends State<ExamplePage> {
// 1. 创建一个控制器
late final OmniCalendarController _controller;
// 用于演示外部控制的状态变量
final bool _showLunar = false;
final bool _showSurroundingDays = true;
late Locale _locale = const Locale('en', 'EN');
@override
void initState() {
super.initState();
// 初始化控制器,可以传入初始日期
_controller = OmniCalendarController(
initialDate: DateTime.now(),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _changeLocale(){
if(_locale == const Locale('en', 'EN')){
setState(() {
_locale = const Locale('zh', 'CN');
});
}else{
setState(() {
_locale = const Locale('en', 'EN');
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Omni Calendar View Demo'),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ElevatedButton(
onPressed: _changeLocale,
child: Text("切换语言")
),
Card(
elevation: 4,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Padding(
padding: EdgeInsets.all(8.0),
child: OmniCalendarView(
controller: _controller,
showLunar: _showLunar,
showSurroundingDays: _showSurroundingDays,
locale: _locale,
onDateSelected: (date) {
print('单选: ${date.toLocal()}');
},
onDateRangeSelected: (dateRange) {
print('范围选择: ${dateRange.start.toLocal()} - ${dateRange.end.toLocal()}');
},
onMonthChanged: (date) {
print('月份切换到: ${date.year}-${date.month}');
},
onHeaderTap: () async {
_controller.jumpToDate(DateTime(2024 , 3, 1));
},
),
),
),
const SizedBox(height: 24),
const Text("外部控制 & 状态查询", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 12),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
ElevatedButton(
onPressed: () {
// 3. 使用控制器跳转到指定日期
_controller.jumpToDate(DateTime(2026, 1, 15));
},
child: const Text('跳转到 2026-01-15'),
),
ElevatedButton(
onPressed: () {
// 4. 使用控制器查询当前状态
final singleDate = _controller.selectedDate;
final range = _controller.selectedDateRange;
String message;
if (range != null && _controller.selectionType == SelectionType.range) {
message = '当前选择范围: ${range.start.toLocal().toString().split(' ')[0]} to ${range.end.toLocal().toString().split(' ')[0]}';
} else if (singleDate != null) {
message = '当前单选日期: ${singleDate.toLocal().toString().split(' ')[0]}';
} else {
message = '当前未选择任何日期';
}
showDialog(
context: context,
builder: (c) => AlertDialog(
title: const Text('当前日历状态'),
content: Text(message),
actions: [
TextButton(onPressed: () => Navigator.pop(c), child: const Text('好的'))
],
),
);
},
child: const Text('查询当前选择'),
),
],
),
],
),
),
),
);
}
}