將以下程式碼複製貼到 main.dart 執行一遍
// main.dart
import 'package:flutter/material.dart';
// 判斷公(西)元是潤年的條件: (4 倍數且非 100 倍數) 或是 400 倍數
bool isLeapYear(int adYear) => (adYear % 4 == 0) && (adYear % 100 != 0) || (adYear % 400 == 0);
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override Widget build(BuildContext context) => MaterialApp(// title: '月曆',
debugShowCheckedModeBanner: false,
theme: ThemeData.dark(),
home: const Scaffold(body: LunarCalender())
);
}
class LunarCalender extends StatefulWidget {
const LunarCalender({super.key});
@override State<LunarCalender> createState() => _LunarCalenderState();
}
class _LunarCalenderState extends State<LunarCalender> {
final today = DateTime.now();
final boxBorder = const BoxDecoration(border: Border(
top: BorderSide(width: 1.0, color: Colors.grey),
left: BorderSide(width: 1.0, color: Colors.grey),
right: BorderSide(width: 1.0, color: Colors.grey),
bottom: BorderSide(width: 1.0, color: Colors.grey),
));
final cross = const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 7);
// 月份: 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 月
List<int> daysofMonth = [31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];// 天數
Widget monthView(int year, int month) { //todo: validate year and month
daysofMonth[2] = isLeapYear(year) ? 29 : 28; //更新二月天數
final y0 = year - 1;// 註: 公(西)元 1 年 1 月 1 日 是 星期日 (weekday = 0)
int weekday = year + (y0 ~/ 4) + (y0 ~/ 400) - (y0 ~/ 100);// 潤年補天數
for (int i = 1; i < month; i ++) { weekday += daysofMonth[i]; } // 直到上個月天數
weekday %= 7;// 當月第 1 天的星期序, 0 是星期日, ..., 同時等於上個月尚需展示的天數
final lastMonth = daysofMonth[month - 1];// 上個月天數
final total = daysofMonth[month] + weekday;// 天數: 當月顯示天數 + 上個月在這個月顯示天數
return GridView.builder(
itemCount: total,
padding: EdgeInsets.zero,
gridDelegate: cross,
itemBuilder: (BuildContext context, int i) {
int atDay = i + 1 - weekday;// 擬顯示的日期, 位置同時與星期序相關
int atMonth = month;// 擬顯示的月份
if (atDay <= 0) {// 修正為上個月的日期
atDay += lastMonth;
atMonth --;
}
return Container(
decoration: boxBorder,
child: Flex(
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [Text("$atMonth 月"), Text("$atDay")]
)
);
}
);
}
@override Widget build(BuildContext context) {
int year = today.year;
int month = today.month;
return Scaffold(
appBar: AppBar(title: Center(child:Text("月曆 西元 $year 年 $month 月"))),
body: Flex(
direction: Axis.vertical,
children: [
const Flex(
direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('星期日'),
Text('星期一'),
Text('星期二'),
Text('星期三'),
Text('星期四'),
Text('星期五'),
Text('星期六')
]
),
Expanded(child: monthView(year, month))
]
)
);
}
}
沒有留言:
張貼留言