Flutter入门(33):Flutter 组件之时间日期选择器(DatePicker,TimerPicker)详解

1. 基本介绍

showDatePicker、showTimePicker 是 flutter 提供的日期选择器弹框。
CalendarDatePicker 是替代 YearPicker、MonthPicker、DayPicker 的新的日期选择控件。
CupertinoDatePicker、CupertinoTimerPicker 是 iOS 风格的 DatePickerView 和 TimePickerView 的日期时间选择器。

2. 示例代码

代码下载地址。如果对你有帮助的话记得给个关注,代码会根据我的 Flutter 专题不断更新。

3. 属性介绍

showDatePicker属性 介绍
context @required BuildContext,上下文 context
initialDate @required DateTime,日历初始化日期
2020-10-12 蓝色圆框.png
firstDate @required DateTime,日历开始日期
lastDate @required DateTime,日历结束日期
currentDate DateTime 当前日期
2020-10-20 蓝边圆圈.png
initialEntryMode DatePickerEntryMode.calendar 与 input 两种,分别为选择器和填写框
selectableDayPredicate (DateTime dayTime){ return true;} 一个返回 bool 值的函数,自定义哪些可选,下文会详解
helpText 左上角文字
helpText.png
cancelText 取消按钮文字
cancelText.png
confirmText 确认按钮文字,上图中 confirmText
locale 地区设置,以后多语言部分在详解
useRootNavigator 是否使用根导航,默认为 true,官方文档也没做详解,暂时没用到
routeSettings 路由设置,官方文档也没做详解,暂时没用到
textDirection 文字方向,TextDirection,DatePickerEntryMode.input 模式时,居左或者居右设置
builder 创建器,和直接创建基本一致,可以定制主题
initialDatePickerMode DatePickerMode.day 与 DatePickerMode.year 两种
errorFormatText 格式错误是下方提示
errorFormatText.png
fieldHintText 输入框默认提示语
fieldLabelText 输入框上方提示语
errorInvalidText 输入了不在 first 与 last 之间的日期提示语
errorInvalidText.png
showTimePicker属性 介绍
context @required BuildContext 上下文
initialTime @required TimeOfDay 设置默认日期
builder 创建器,和直接创建基本一致,可以定制主题
initialEntryMode 默认为 TimePickerEntryMode.dial。input 样式其实就是收起后的样子
helpText 左上角文字
helpText.png
cancelText 取消按钮文字
cancelText.png
confirmText 确认按钮文字,上图中 confirmText
useRootNavigator 是否使用根导航,默认为 true,官方文档也没做详解,暂时没用到
routeSettings 路由设置,官方文档也没做详解,暂时没用到
CalendarDatePicker属性 介绍
initialDate @required DateTime 初始化选中日期
firstDate @required DateTime 最小可选日期
lastDate @required DateTime 最大可选日期
currentDate DateTime 当前选中日期
onDateChanged @required 选中日期改变回调函数
onDisplayedMonthChanged 月份改变回调函数
initialCalendarMode DatePickerMode.day 日期选择器样式
selectableDayPredicate 筛选日期可不可点回调函数
CupertinoTimerPicker属性 介绍
mode 展示模式,默认为 CupertinoTimerPickerMode.hms
initialTimerDuration 默认选中事时间,默认为 Duration.zero
minuteInterval 分钟间隔

secondInterval 秒间隔
alignment | 对齐方式
backgroundColor | 背景颜色
onTimerDurationChanged | @required 滑动后,每次改变回调函数

CupertinoDatePicker属性 | 介绍
mode | 展示模式, 默认为 CupertinoDatePickerMode.dateAndTime,
onDateTimeChanged | @required 日期改变回调函数
initialDateTime | DateTime 默认选中日期
minimumDate | 最小可选日期
maximumDate | 最大可选日期
minimumYear | 最小可选年份
maximumYear | 最大可选年份
minuteInterval | 分钟间隔
use24hFormat | 是否使用24小时制
backgroundColor | 背景色

4. showDatePicker 详解

4.1 日期选择弹窗

import 'package:flutter/material.dart';

class FMDatePickerVC extends StatefulWidget{
  @override
  FMDatePickerState createState() => FMDatePickerState();
}

class FMDatePickerState extends State <FMDatePickerVC> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("DatePicker"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDatePicker(context),
          // _showDatePickerForYear(context),
          // _showDatePickerForInput(context),
        ],
      ),
    );
  }

  RaisedButton _showDatePicker(context){
    return RaisedButton(
      child: Text("showDatePicker"),
      onPressed: (){
        showDatePicker(
            context: context,
            initialDate: DateTime.now(), // 初始化选中日期
            firstDate: DateTime(2020, 6),  // 开始日期
            lastDate: DateTime(2021, 6),  // 结束日期
            // initialEntryMode: DatePickerEntryMode.input,  // 日历弹框样式

            textDirection: TextDirection.ltr,  // 文字方向

            currentDate: DateTime(2020, 10, 20),  // 当前日期
            helpText: "helpText", // 左上方提示
            cancelText: "cancelText",  // 取消按钮文案
            confirmText: "confirmText",  // 确认按钮文案

            errorFormatText: "errorFormatText",  // 格式错误提示
            errorInvalidText: "errorInvalidText",  // 输入不在 first 与 last 之间日期提示

            fieldLabelText: "fieldLabelText",  // 输入框上方提示
            fieldHintText: "fieldHintText",  // 输入框为空时内部提示

            initialDatePickerMode: DatePickerMode.day, // 日期选择模式,默认为天数选择
            useRootNavigator: true, // 是否为根导航器
            // 设置不可选日期,这里将 2020-10-15,2020-10-16,2020-10-17 三天设置不可选
            selectableDayPredicate: (dayTime){
              if(dayTime == DateTime(2020, 10, 15) || dayTime == DateTime(2020, 10, 16) || dayTime == DateTime(2020, 10, 17)) {
                return false;
              }
              return true;
            }
        );
      },
    );
  }
}
showDatePicker day.png

4.2 年份选择器

  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("DatePicker"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDatePicker(context),
          _showDatePickerForYear(context),
         //  _showDatePickerForInput(context),
        ],
      ),
    );
  }

  RaisedButton _showDatePickerForYear(context){
    return RaisedButton(
      child: Text("showDatePicker - YearMode"),
      onPressed: (){
        showDatePicker(
          context: context,
          initialDate: DateTime.now(), // 初始化选中日期
          firstDate: DateTime(2018, 6),  // 开始日期
          lastDate: DateTime(2025, 6),  // 结束日期
          currentDate: DateTime(2020, 10, 20),  // 当前日期
          helpText: "helpText", // 左上方提示
          cancelText: "cancelText",  // 取消按钮文案
          confirmText: "confirmText",  // 确认按钮文案

          initialDatePickerMode: DatePickerMode.year, // 日期选择模式,默认为天数选择
        );
      },
    );
  }
showDatePicker year.png

4.3 日期输入框

  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("DatePicker"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDatePicker(context),
          _showDatePickerForYear(context),
          _showDatePickerForInput(context),
        ],
      ),
    );
  }

  RaisedButton _showDatePickerForInput(context){
    return RaisedButton(
      child: Text("showDatePicker - InputMode"),
      onPressed: (){
        showDatePicker(
            context: context,
            initialDate: DateTime.now(), // 初始化选中日期
            firstDate: DateTime(2020, 6),  // 开始日期
            lastDate: DateTime(2021, 6),  // 结束日期
            initialEntryMode: DatePickerEntryMode.input,  // 日历弹框样式

            textDirection: TextDirection.ltr,  // 文字方向

            currentDate: DateTime(2020, 10, 20),  // 当前日期
            helpText: "helpText", // 左上方提示
            cancelText: "cancelText",  // 取消按钮文案
            confirmText: "confirmText",  // 确认按钮文案

            errorFormatText: "errorFormatText",  // 格式错误提示
            errorInvalidText: "errorInvalidText",  // 输入不在 first 与 last 之间日期提示

            fieldLabelText: "fieldLabelText",  // 输入框上方提示
            fieldHintText: "fieldHintText",  // 输入框为空时内部提示

            initialDatePickerMode: DatePickerMode.day, // 日期选择模式,默认为天数选择
            useRootNavigator: true, // 是否为根导航器
            // 设置不可选日期,这里将 2020-10-15,2020-10-16,2020-10-17 三天设置不可选
            selectableDayPredicate: (dayTime){
              if(dayTime == DateTime(2020, 10, 15) || dayTime == DateTime(2020, 10, 16) || dayTime == DateTime(2020, 10, 17)) {
                return false;
              }
              return true;
            }
        );
      },
    );
  }
showDatePicker input normal.png

showDatePicker input errorFormat.png

showDatePicker input errorInvalid.png

showDatePicker input rtl.png

4.4 日期选择器主题设置

主题 Theme 本身就是一个功能很庞大的东西,这里不多描述,有兴趣可以自行了解。

  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("DatePicker"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDatePicker(context),
          _showDatePickerForYear(context),
          _showDatePickerForInput(context),
          _showDatePickerForTheme(context),
        ],
      ),
    );
  }

  RaisedButton _showDatePickerForTheme(context){
    return RaisedButton(
      child: Text("showDatePicker - InputMode"),
      onPressed: (){
        showDatePicker(
            context: context,
            builder: (context, child) {
              return Theme(
                data: ThemeData(
                  cardColor: Colors.red,
                  brightness: Brightness.dark,
                ),
                child: child,
              );
            },
          initialDate: DateTime.now(), // 初始化选中日期
          firstDate: DateTime(2018, 6),  // 开始日期
          lastDate: DateTime(2025, 6),  // 结束日期
          currentDate: DateTime(2020, 10, 20),  // 当前日期
          helpText: "helpText", // 左上方提示
          cancelText: "cancelText",  // 取消按钮文案
          confirmText: "confirmText",  // 确认按钮文案

          initialDatePickerMode: DatePickerMode.year, // 日期选择模式,默认为天数选择
        );
      },
    );
  }
showDatePicker theme.png

5. showTimePicker 详解

和 showDatePicker 基本一样,不做赘述。

  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("DatePicker"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDatePicker(context),
          _showDatePickerForYear(context),
          _showDatePickerForInput(context),
          _showDatePickerForTheme(context),
          _showTimePicker(context),
        ],
      ),
    );
  }

  RaisedButton _showTimePicker(context){
    return RaisedButton(
      child: Text("showTimePicker - InputMode"),
      onPressed: (){
        showTimePicker(
          context: context,
          initialTime: TimeOfDay(hour: 10, minute: 30),
          cancelText: "cancelText",
          helpText: "helpText",
          confirmText: "confirmText"
        );
      },
    );
  }
showTimePicker dial.png

showTimePicker input.png

6. CalendarDatePicker 详解

  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("DatePicker"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDatePicker(context),
          _showDatePickerForYear(context),
          _showDatePickerForInput(context),
          _showDatePickerForTheme(context),
          _showTimePicker(context),
          Text("CalendarDatePicker day"),
          _calendarDatePicker(DatePickerMode.day),
          Text("CalendarDatePicker year"),
          _calendarDatePicker(DatePickerMode.year),
        ],
      ),
    );
  }

  CalendarDatePicker _calendarDatePicker(DatePickerMode mode){
    return CalendarDatePicker(
      initialDate: DateTime.now(), // 初始化选中日期
      currentDate: DateTime(2020, 10, 18),
      firstDate: DateTime(2020, 9, 10),  // 开始日期
      lastDate: DateTime(2022, 9, 10),  // 结束日期
      initialCalendarMode: mode, // 日期选择样式
      // 选中日期改变回调函数
      onDateChanged: (dateTime){
        print("onDateChanged $dateTime");
      },
      // 月份改变回调函数
      onDisplayedMonthChanged: (dateTime){
        print("onDisplayedMonthChanged $dateTime");
      },
      // 筛选日期可不可点回调函数
      selectableDayPredicate: (dayTime){
        if(dayTime == DateTime(2020, 10, 15) || dayTime == DateTime(2020, 10, 16) || dayTime == DateTime(2020, 10, 17)) {
          return false;
        }
        return true;
      }
    );
  }
CalendarDatePicker year and day.png

7. CupertinoTimerPicker 详解

注意改变 mode 时,不要使用热重载,会报错。

  CupertinoTimerPicker _cupertinoTimePicker(CupertinoTimerPickerMode mode){
    return CupertinoTimerPicker(
      mode: mode, // 展示模式
      initialTimerDuration: Duration(hours: 5, minutes: 10), // 默认选中事时间
      minuteInterval: 10, // 分钟间隔
      secondInterval: 10, // 秒间隔
      alignment: Alignment.center, // 对齐方式
      backgroundColor: Colors.yellow, // 背景颜色
      // 滑动后,每次改变回调函数
      onTimerDurationChanged: (dayTime){
        print("onTimerDurationChanged $dayTime");
      },
    );
  }
CupertinoTimerPicker.png

8. CupertinoDatePicker 详解

CupertinoDatePicker 直接使用在 ListView 中会报错,这里我用一个固定大小的 Container 作为父容器。

  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("DatePicker"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDatePicker(context),
          _showDatePickerForYear(context),
          _showDatePickerForInput(context),
          _showDatePickerForTheme(context),
          _showTimePicker(context),

          Text("CalendarDatePicker day"),
          _calendarDatePicker(DatePickerMode.day),
          Text("CalendarDatePicker year"),
          _calendarDatePicker(DatePickerMode.year),

          Text("_cupertinoTimePicker - hms"),
          _cupertinoTimePicker(CupertinoTimerPickerMode.hms),
          Text("_cupertinoTimePicker - hm"),
          _cupertinoTimePicker(CupertinoTimerPickerMode.hm),
          Text("_cupertinoTimePicker - ms"),
          _cupertinoTimePicker(CupertinoTimerPickerMode.ms),

          Text("CupertinoDatePicker - dateAndTime"),
          _cupertinoDatePicker(CupertinoDatePickerMode.dateAndTime),
          Text("CupertinoDatePicker - date"),
          _cupertinoDatePicker(CupertinoDatePickerMode.date),
        ],
      ),
    );
  }

  Container _cupertinoDatePicker(CupertinoDatePickerMode mode){
    return Container(
      height: 200,
      child: CupertinoDatePicker(
        mode: mode, // 展示模式, 默认为 dateAndTime
        initialDateTime: DateTime(2020, 10, 10), // 默认选中日期
        minimumDate: DateTime(2020, 10, 10), // 最小可选日期
        maximumDate: DateTime(2021, 10, 10), // 最大可选日期

        minimumYear: 2020, // 最小可选年份
        maximumYear: 2021, // 最大可选年份

        minuteInterval: 10, // 分钟间隔

        use24hFormat: true, // 是否采用24小时制
        backgroundColor: Colors.cyan, // 背景色

        onDateTimeChanged: (dayTime){
          print("onDateTimeChanged $dayTime");
        },
      ),
    );
  }
CupertinoDatePicker.png

9. 技术小结

日期选择器样式比较多,但是属性偏少,需要耐心尝试各种不同的选择器。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349