一統天下 flutter - widget 選擇類: showDatePicker()/showTimePicker/CalendarDatePicker - 日期選擇和時間選擇

源碼 https://github.com/webabcd/flutter_demo
作者 webabcd

一統天下 flutter - widget 選擇類: showDatePicker()/showTimePicker/CalendarDatePicker - 日期選擇和時間選擇

示例如下:

lib\widget\selection\time_picker.dart

/*
 * showDatePicker()/showTimePicker/CalendarDatePicker - 日期選擇和時間選擇
 */

import 'package:flutter/material.dart';
import 'package:flutter_demo/helper.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

class TimePickerDemo extends StatefulWidget {
  const TimePickerDemo({Key? key}) : super(key: key);

  @override
  _TimePickerDemoState createState() => _TimePickerDemoState();
}

class _TimePickerDemoState extends State<TimePickerDemo> {

  /// 切換語言
  var _locale = const Locale("en");
  changeLocale(Locale locale) {
    setState(() {
      _locale = locale;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const _MyHomePage(),

      /// 國際化相關
      locale: _locale,
      supportedLocales: const [
        Locale("en"),
        Locale("zh"),
      ],
      localizationsDelegates: const [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
    );
  }
}

class _MyHomePage extends StatefulWidget {
  const _MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<_MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.orange,
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            /// 彈出日曆選擇控件
            _showDatePicker(context),
            /// 彈出日曆選擇控件,並指定其主題
            _showDatePickerUseTheme(context),
            /// 彈出時間選擇控件
            _showTimePicker(context),
            /// 彈出時間選擇控件,並指定其主題,並設置爲 24 小時制
            _showTimePickerUseThemeAnd24HourFormat(context),
            /// 顯示日曆選擇控件(直接在當前頁面上顯示,而不是彈出來)
            SizedBox(width: 300, height: 150, child: _calendarDatePicker(),),
          ],
        ),
      ),
      persistentFooterButtons: [
        MyButton(
          onPressed: () {
            final myApp = context.findAncestorStateOfType<_TimePickerDemoState>()!;
            myApp.changeLocale(const Locale('zh'));
          },
          child: const Text("中文"),
        ),
        MyButton(
          onPressed: () {
            final myApp = context.findAncestorStateOfType<_TimePickerDemoState>()!;
            myApp.changeLocale(const Locale('en'));
          },
          child: const Text("英文"),
        ),
      ],
    );
  }

  MyButton _showDatePicker(context) {
    return MyButton(
      child: const Text("showDatePicker"),
      onPressed: () async {
        /// 彈出日曆選擇控件
        var selectedDate = await showDatePicker(
          /// BuildContext
          context: context,
          /// 國際化
          locale: context.findAncestorStateOfType<_TimePickerDemoState>()!._locale,

          /// 日曆選擇框的樣式
          ///   calendar - 默認日曆選擇,也可以手工輸入
          ///   input - 默認手工輸入,也可以日曆選擇
          ///   calendarOnly - 僅日曆選擇
          ///   inputOnly - 僅手工輸入
          initialEntryMode: DatePickerEntryMode.calendar,
          /// day - 初始在選擇日期的頁面
          /// year - 初始在選擇年份的頁面
          initialDatePickerMode: DatePickerMode.day,

          /// 當前日期
          currentDate: DateTime.now(),
          /// 默認的選中日期
          initialDate: DateTime.now().add(const Duration(days: -10)),
          /// 支持的最小的可選日期
          firstDate: DateTime.now().add(const Duration(days: -365 * 2)),
          /// 支持的最大的可選日期
          lastDate: DateTime.now().add(const Duration(days: 365 * 2)),
          /// 用於設置哪些日期可選,哪些日期不可選
          selectableDayPredicate: (dayTime) {
            if (dayTime.isAfter(DateTime.now().add(const Duration(days: 3))) &&
                dayTime.isBefore(DateTime.now().add(const Duration(days: 10))) ) {
              return false; /// 不可選
            }
            return true;    /// 可選
          },
          /// 左上角文字
          helpText: "helpText",
          /// 取消按鈕文字
          cancelText: "cancelText",
          /// 確認按鈕文字
          confirmText: "confirmText",
          /// 輸入日期格式錯誤時的提示
          errorFormatText: "errorFormatText",
          /// 輸入日期爲不可選日期時的提示
          errorInvalidText: "errorInvalidText",
          /// 輸入日期時,輸入框上方的提示
          fieldLabelText: "fieldLabelText",
          /// 輸入日期時,輸入框內容爲空時的提示,就是 placeholder 的意思
          fieldHintText: "fieldHintText",
        );

        /// 獲取選中的日期
        showToast(context, "selectedDate:$selectedDate");
      },
    );
  }

  MyButton _showDatePickerUseTheme(context){
    return MyButton(
      child: const Text("showDatePicker(自定義主題)"),
      onPressed: () async {
        /// 彈出日曆選擇控件,並指定其主題
        var selectedDate = await showDatePicker(
          context: context,
          locale: context.findAncestorStateOfType<_TimePickerDemoState>()!._locale,
          initialDate: DateTime.now().add(const Duration(days: -10)),
          firstDate: DateTime.now().add(const Duration(days: -365 * 2)),
          lastDate: DateTime.now().add(const Duration(days: 365 * 2)),
          builder: (context, child) {
            return Theme( /// 使用自定義主題
              data: ThemeData(
                cardColor: Colors.red,
                brightness: Brightness.dark,
              ),
              child: child!,
            );
          },
        );

        /// 獲取選中的日期
        showToast(context, "selectedDate:$selectedDate");
      },
    );
  }

  MyButton _showTimePicker(context){
    return MyButton(
      child: const Text("showTimePicker"),
      onPressed: () async {
        /// 彈出時間選擇控件
        var selectedTime = await showTimePicker(
          /// BuildContext
          context: context,
          /// 默認的選中時間
          initialTime: const TimeOfDay(hour: 10, minute: 30),
          /// 時間選擇框的樣式
          ///   dial - 默認錶盤選擇,也可以手工輸入
          ///   input - 默認手工輸入,也可以錶盤選擇
          ///   dialOnly - 僅錶盤選擇
          ///   inputOnly - 僅手工輸入
          initialEntryMode: TimePickerEntryMode.dial,
          /// 左上角文字
          helpText: "helpText",
          /// 取消按鈕文字
          cancelText: "cancelText",
          /// 確認按鈕文字
          confirmText: "confirmText",
          /// 輸入的時間非法時顯示的信息
          errorInvalidText: "errorInvalidText",
          /// 輸入時間時,小時框下的提示文字
          hourLabelText: "hourLabelText",
          /// 輸入時間時,分鐘框下的提示文字
          minuteLabelText: "minuteLabelText",
        );

        /// 獲取選中的時間
        showToast(context, "selectedTime:$selectedTime");
      },
    );
  }

  MyButton _showTimePickerUseThemeAnd24HourFormat(context){
    return MyButton(
      child: const Text("showTimePicker(自定義主題,以及 24 小時制)"),
      onPressed: () async {
        /// 彈出時間選擇控件,並指定其主題,並設置爲 24 小時制
        var selectedTime = await showTimePicker(
          context: context,
          initialTime: const TimeOfDay(hour: 10, minute: 30),
          initialEntryMode: TimePickerEntryMode.dial,
          builder: (context, child) {
            return Theme( /// 使用自定義主題
              data: ThemeData(
                cardColor: Colors.red,
                brightness: Brightness.dark,
              ),
              child: MediaQuery(
                data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true), /// 使用 24 小時制
                child: child!,
              ),
            );
          },
        );

        /// 獲取選中的時間
        showToast(context, "selectedTime:$selectedTime");
      },
    );
  }

  /// 顯示日曆選擇控件(直接在當前頁面上顯示,而不是彈出來)
  /// 類似的 ios 風格的控件有 CupertinoDatePicker, CupertinoTimerPicker
  CalendarDatePicker _calendarDatePicker() {
    return CalendarDatePicker(
      currentDate: DateTime.now(),
      initialDate: DateTime.now().add(const Duration(days: -10)),
      firstDate: DateTime.now().add(const Duration(days: -365 * 2)),
      lastDate: DateTime.now().add(const Duration(days: 365 * 2)),
      initialCalendarMode: DatePickerMode.day,
      /// 選擇的日期發生變化時
      onDateChanged: (dateTime){
        log("onDateChanged:$dateTime");
      },
      /// 因爲切換年或月導致的選擇的日期發生變化時
      onDisplayedMonthChanged: (dateTime){
        log("onDisplayedMonthChanged:$dateTime");
      },
    );
  }
}


源碼 https://github.com/webabcd/flutter_demo
作者 webabcd

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章