2024年8月21日 星期三

使用 flutter 編寫簡單的萬年月曆

將以下程式碼複製貼到 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))
        ]
      )
    );    
  }
}

沒有留言:

張貼留言

使用 pcie 轉接器連接 nvme SSD

之前 AM4 主機板使用 pcie ssd, 但主機板故障了沒辦法上網, 只好翻出以前買的 FM2 舊主機板, 想辦法讓老主機復活, 但舊主機板沒有 nvme 的界面, 因此上網買了 pcie 轉接器用來連接 nvme ssd, 遺憾的是 grub2 bootloader 無法識...