一统天下 flutter - widget 选择类: showDatePicker()/showTimePicker/CalendarDatePicker - 日期选择和时间选择

发布时间 2023-04-20 14:10:43作者: webabcd

源码 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