zoukankan      html  css  js  c++  java
  • flutter 时间选择器 年月日季度周 (在第三方基础上修改的)

    在第三方flutter_picker 基础上修改了时间选择器 年月日季度周 选择器

          

    datePicker.dart

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_screenutil/flutter_screenutil.dart';
    import 'package:semf_flutter/generated/i18n.dart';
    import 'dart:async';
    
    const bool __printDebug = false;
    
    /// Picker selected callback.
    typedef PickerSelectedCallback = void Function(
        Picker picker, int index, List<int> selecteds);
    
    /// Picker confirm callback.
    typedef PickerConfirmCallback = void Function(
        Picker picker, List<int> selecteds);
    
    /// Picker
    class Picker {
      static const double DefaultTextSize = 20.0;
    
      /// Index of currently selected items
      List<int> selecteds;
    
      /// Picker adapter, Used to provide data and generate widgets
      final PickerAdapter adapter;
    
      /// insert separator before picker columns
      final List<PickerDelimiter> delimiter;
    
      final VoidCallback onCancel;
      final PickerSelectedCallback onSelect;
      final PickerConfirmCallback onConfirm;
    
      /// When the previous level selection changes, scroll the child to the first item.
      final changeToFirst;
    
      /// Specify flex for each column
      final List<int> columnFlex;
    
      final Widget title;
      final Widget cancel;
      final Widget confirm;
      final String cancelText;
      final String confirmText;
    
      final double height;
    
      /// Height of list item
      final double itemExtent;
    
      final TextStyle textStyle,
          cancelTextStyle,
          confirmTextStyle,
          selectedTextStyle;
      final TextAlign textAlign;
    
      /// Text scaling factor
      final double textScaleFactor;
    
      final EdgeInsetsGeometry columnPadding;
      final Color backgroundColor, headercolor, containerColor;
    
      /// Hide head
      final bool hideHeader;
    
      /// Show pickers in reversed order
      final bool reversedOrder;
    
      /// List item loop
      final bool looping;
    
      /// Delay generation for smoother animation, This is the number of milliseconds to wait. It is recommended to > = 200
      final int smooth;
    
      final Widget footer;
    
      final Decoration headerDecoration;
    
      final double magnification;
      final double diameterRatio;
      final double squeeze;
    
      Widget _widget;
      PickerWidgetState _state;
    
      Picker(
          {this.adapter,
          this.delimiter,
          this.selecteds,
          this.height = 150.0,
          this.itemExtent = 28.0,
          this.columnPadding,
          this.textStyle,
          this.cancelTextStyle,
          this.confirmTextStyle,
          this.selectedTextStyle,
          this.textAlign = TextAlign.start,
          this.textScaleFactor,
          this.title,
          this.cancel,
          this.confirm,
          this.cancelText,
          this.confirmText,
          this.backgroundColor = Colors.white,
          this.containerColor,
          this.headercolor,
          this.changeToFirst = false,
          this.hideHeader = false,
          this.looping = false,
          this.reversedOrder = false,
          this.headerDecoration,
          this.columnFlex,
          this.footer,
          this.smooth,
          this.magnification = 1.0,
          this.diameterRatio = 1.1,
          this.squeeze = 1.45,
          this.onCancel,
          this.onSelect,
          this.onConfirm})
          : assert(adapter != null);
    
      Widget get widget => _widget;
    
      PickerWidgetState get state => _state;
      int _maxLevel = 1;
    
      /// 生成picker控件
      /// Build picker control
      Widget makePicker([ThemeData themeData, bool isModal = false]) {
        _maxLevel = adapter.maxLevel;
        adapter.picker = this;
        adapter.initSelects();
        _widget =
            _PickerWidget(picker: this, themeData: themeData, isModal: isModal);
        return _widget;
      }
    
      /// show picker
      void show(ScaffoldState state, [ThemeData themeData]) {
        state.showBottomSheet((BuildContext context) {
          return makePicker(themeData);
        });
      }
    
      /// 获取当前选择的值
      /// Get the value of the current selection
      List getSelectedValues() {
        return adapter.getSelectedValues();
      }
    
      /// 取消
      void doCancel(BuildContext context) {
        if (onCancel != null) onCancel();
        Navigator.of(context).pop<List<int>>(null);
        _widget = null;
      }
    
      /// 确定
      void doConfirm(BuildContext context) {
        if (onConfirm != null) onConfirm(this, selecteds);
        Navigator.of(context).pop();
        _widget = null;
      }
    
      /// 弹制更新指定列的内容
      /// 当 onSelect 事件中,修改了当前列前面的列的内容时,可以调用此方法来更新显示
      void updateColumn(int index, [bool all = false]) {
        if (all) {
          _state.update();
          return;
        }
        adapter.setColumn(index - 1);
        _state._keys[index].currentState.update();
      }
    }
    
    /// 分隔符
    class PickerDelimiter {
      final Widget child;
      final int column;
    
      PickerDelimiter({this.child, this.column = 1}) : assert(child != null);
    }
    
    /// picker data list item
    class PickerItem<T> {
      /// 显示内容
      final Widget text;
    
      /// 数据值
      final T value;
    
      /// 子项
      final List<PickerItem<T>> children;
    
      PickerItem({this.text, this.value, this.children});
    }
    
    class _PickerWidget<T> extends StatefulWidget {
      final Picker picker;
      final ThemeData themeData;
      final bool isModal;
    
      _PickerWidget(
          {Key key, @required this.picker, @required this.themeData, this.isModal})
          : super(key: key);
    
      @override
      PickerWidgetState createState() =>
          PickerWidgetState<T>(picker: this.picker, themeData: this.themeData);
    }
    
    class PickerWidgetState<T> extends State<_PickerWidget> {
      final Picker picker;
      final ThemeData themeData;
    
      PickerWidgetState({Key key, @required this.picker, @required this.themeData});
    
      ThemeData theme;
      final List<FixedExtentScrollController> scrollController = [];
      final List<GlobalKey<_StateViewState>> _keys = [];
    
      @override
      void initState() {
        super.initState();
        theme = themeData;
        picker._state = this;
        picker.adapter.doShow();
    
        if (scrollController.length == 0) {
          for (int i = 0; i < picker._maxLevel; i++) {
            scrollController
                .add(FixedExtentScrollController(initialItem: picker.selecteds[i]));
            _keys.add(GlobalKey(debugLabel: i.toString()));
          }
        }
      }
    
      void update() {
        setState(() {});
      }
    
      // var ref = 0;
      @override
      Widget build(BuildContext context) {
        // print("picker build ${ref++}");
        ScreenUtil.instance = ScreenUtil( 750, height: 1334)..init(context);
        if (_wait && picker.smooth != null && picker.smooth > 0) {
          Future.delayed(Duration(milliseconds: picker.smooth), () {
            if (!_wait) return;
            setState(() {
              _wait = false;
            });
          });
        } else
          _wait = false;
    
        var _body = <Widget>[];
        if (!picker.hideHeader) {
          _body.add(DecoratedBox(
            child: Row(
              children: _buildHeaderViews(),
            ),
            decoration: picker.headerDecoration ??
                BoxDecoration(
                  border: Border(
                    top: BorderSide(color: theme.dividerColor,  0.5),
                    bottom: BorderSide(color: theme.dividerColor,  0.5),
                  ),
                  color: picker.headercolor == null
                      ? theme.bottomAppBarColor
                      : picker.headercolor,
                ),
          ));
        }
        _body.add(_wait
            ? Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: _buildViews(),
              )
            : AnimatedSwitcher(
                duration: Duration(milliseconds: 300),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: _buildViews(),
                ),
              ));
    
        if (picker.footer != null) _body.add(picker.footer);
        Widget v = Column(
          mainAxisSize: MainAxisSize.min,
          children: _body,
        );
        if (widget.isModal != null && widget.isModal) {
          v = GestureDetector(
            onTap: () {},
            child: v,
          );
        }
        return v;
      }
    
      List<Widget> _headerItems;
    
      List<Widget> _buildHeaderViews() {
        if (_headerItems != null) return _headerItems;
        if (theme == null) theme = Theme.of(context);
        List<Widget> items = [];
    
        if (picker.cancel != null) {
          items.add(DefaultTextStyle(
              style: picker.cancelTextStyle ??
                  TextStyle(
                      color: theme.accentColor, fontSize: Picker.DefaultTextSize),
              child: picker.cancel));
        } else {
          String _cancelText = picker.cancelText ?? S.of(context).datePicker_Cancel;
          if (_cancelText != null || _cancelText != "") {
            items.add(FlatButton(
                onPressed: () {
                  picker.doCancel(context);
                },
                child: Text(_cancelText,
                    overflow: TextOverflow.ellipsis,
                    style: picker.cancelTextStyle ??
                        TextStyle(
                            color: theme.accentColor,
                            fontSize: Picker.DefaultTextSize))));
          }
        }
    
        items.add(Expanded(
            child: Center(
          //alignment: Alignment.center,
          child: picker.title == null
              ? picker.title
              : DefaultTextStyle(
                  style: TextStyle(
                      fontSize: Picker.DefaultTextSize,
                      color: theme.textTheme.title.color),
                  child: picker.title),
        )));
    
        if (picker.confirm != null) {
          items.add(DefaultTextStyle(
              style: picker.confirmTextStyle ??
                  TextStyle(
                      color: theme.accentColor, fontSize: Picker.DefaultTextSize),
              child: picker.confirm));
        } else {
          String _confirmText =
              picker.confirmText ?? S.of(context).datePicker_Confirm;
          if (_confirmText != null || _confirmText != "") {
            items.add(FlatButton(
                onPressed: () {
                  picker.doConfirm(context);
                },
                child: Text(_confirmText,
                    overflow: TextOverflow.ellipsis,
                    style: picker.confirmTextStyle ??
                        TextStyle(
                            color: theme.accentColor,
                            fontSize: Picker.DefaultTextSize))));
          }
        }
    
        _headerItems = items;
        return items;
      }
    
      bool _changeing = false;
      bool _wait = true;
      final Map<int, int> lastData = {};
    
      List<Widget> _buildViews() {
        if (__printDebug) print("_buildViews");
        if (theme == null) theme = Theme.of(context);
    
        List<Widget> items = [];
    
        PickerAdapter adapter = picker.adapter;
        if (adapter != null) adapter.setColumn(-1);
    
        if (adapter != null && adapter.length > 0) {
          var _decoration = BoxDecoration(
            color: picker.containerColor == null
                ? theme.dialogBackgroundColor
                : picker.containerColor,
          );
    
          for (int i = 0; i < picker._maxLevel; i++) {
            Widget view = Expanded(
              flex: adapter.getColumnFlex(i),
              child: Container(
                padding: picker.columnPadding,
                height: picker.height,
                decoration: _decoration,
                child: _wait
                    ? null
                    : _StateView(
                        key: _keys[i],
                        builder: (context) {
                          adapter.setColumn(i - 1);
                          var _length = adapter.length;
                          var _view = CupertinoPicker.builder(
                            backgroundColor: picker.backgroundColor,
                            scrollController: scrollController[i],
                            itemExtent: picker.itemExtent,
                            // looping: picker.looping,
                            magnification: picker.magnification,
                            diameterRatio: picker.diameterRatio,
                            squeeze: picker.squeeze,
                            onSelectedItemChanged: (int _index) {
                              if (__printDebug) print("onSelectedItemChanged");
                              var index = _index % _length;
                              picker.selecteds[i] = index;
                              updateScrollController(i);
                              adapter.doSelect(i, index);
                              if (picker.changeToFirst) {
                                for (int j = i + 1;
                                    j < picker.selecteds.length;
                                    j++) {
                                  picker.selecteds[j] = 0;
                                  scrollController[j].jumpTo(0.0);
                                }
                              }
                              if (picker.onSelect != null)
                                picker.onSelect(picker, i, picker.selecteds);
    
                              _keys[i].currentState.update();
                              if (adapter.isLinkage) {
                                for (int j = i + 1;
                                    j < picker.selecteds.length;
                                    j++) {
                                  adapter.setColumn(j - 1);
                                  _keys[j].currentState.update();
                                }
                              }
                            },
                            itemBuilder: (context, index) {
                              adapter.setColumn(i - 1);
                              return adapter.buildItem(context, index % _length);
                            },
                            childCount: picker.looping ? null : _length,
                          );
    
                          if (!picker.changeToFirst &&
                              picker.selecteds[i] >= _length) {
                            Timer(Duration(milliseconds: 100), () {
                              if (__printDebug) print("timer last");
                              adapter.setColumn(i - 1);
                              var _len = adapter.length;
                              scrollController[i].jumpToItem(
                                  (_len < _length ? _len : _length) - 1);
                            });
                          }
    
                          return _view;
                        },
                      ),
              ),
            );
            items.add(view);
          }
        }
    
        if (picker.delimiter != null && !_wait) {
          for (int i = 0; i < picker.delimiter.length; i++) {
            var o = picker.delimiter[i];
            if (o.child == null) continue;
            var item = Container(child: o.child, height: picker.height);
            if (o.column < 0)
              items.insert(0, item);
            else if (o.column >= items.length)
              items.add(item);
            else
              items.insert(o.column, item);
          }
        }
    
        if (picker.reversedOrder) return items.reversed.toList();
    
        return items;
      }
    
      void updateScrollController(int i) {
        if (_changeing || !picker.adapter.isLinkage) return;
        _changeing = true;
        for (int j = 0; j < picker.selecteds.length; j++) {
          if (j != i) {
            if (scrollController[j].position.maxScrollExtent == null) continue;
            scrollController[j].position.notifyListeners();
          }
        }
        _changeing = false;
      }
    }
    
    /// 选择器数据适配器
    abstract class PickerAdapter<T> {
      Picker picker;
    
      int getLength();
    
      int getMaxLevel();
    
      void setColumn(int index);
    
      void initSelects();
    
      Widget buildItem(BuildContext context, int index);
    
      Widget makeText(Widget child, String text, bool isSel) {
        return new Center(
            //alignment: Alignment.center,
            child: DefaultTextStyle(
                overflow: TextOverflow.ellipsis,
                maxLines: 1,
                textAlign: picker.textAlign,
                style: picker.textStyle ??
                    TextStyle(
                        color: Colors.black87, fontSize: Picker.DefaultTextSize),
                child: child != null
                    ? child
                    : Text(text,
                        textScaleFactor: picker.textScaleFactor,
                        style: (isSel ? picker.selectedTextStyle : null))));
      }
    
      Widget makeTextEx(
          Widget child, String text, Widget postfix, Widget suffix, bool isSel) {
        List<Widget> items = [];
        if (postfix != null) items.add(postfix);
        items.add(
            child ?? Text(text, style: (isSel ? picker.selectedTextStyle : null)));
        if (suffix != null) items.add(suffix);
    
        var _txtColor = Colors.black87;
        var _txtSize = Picker.DefaultTextSize;
        if (isSel && picker.selectedTextStyle != null) {
          if (picker.selectedTextStyle.color != null)
            _txtColor = picker.selectedTextStyle.color;
          if (picker.selectedTextStyle.fontSize != null)
            _txtSize = picker.selectedTextStyle.fontSize;
        }
    
        return new Center(
            //alignment: Alignment.center,
            child: DefaultTextStyle(
                overflow: TextOverflow.ellipsis,
                maxLines: 1,
                textAlign: picker.textAlign,
                style: picker.textStyle ??
                    TextStyle(color: _txtColor, fontSize: _txtSize),
                child: Wrap(
                  children: items,
                )));
      }
    
      String getText() {
        return getSelectedValues().toString();
      }
    
      List<T> getSelectedValues() {
        return [];
      }
    
      void doShow() {}
    
      void doSelect(int column, int index) {}
    
      int getColumnFlex(int column) {
        if (picker.columnFlex != null && column < picker.columnFlex.length)
          return picker.columnFlex[column];
        return 1;
      }
    
      int get maxLevel => getMaxLevel();
    
      /// Content length of current column
      int get length => getLength();
    
      String get text => getText();
    
      // 是否联动,即后面的列受前面列数据影响
      bool get isLinkage => getIsLinkage();
    
      @override
      String toString() {
        return getText();
      }
    
      bool getIsLinkage() {
        return true;
      }
    
      /// 通知适配器数据改变
      void notifyDataChanged() {
        if (picker != null && picker.state != null) {
          picker.adapter.doShow();
          picker.adapter.initSelects();
          for (int j = 0; j < picker.selecteds.length; j++)
            picker.state.scrollController[j].jumpToItem(picker.selecteds[j]);
        }
      }
    }
    
    /// Picker DateTime Adapter Type
    class PickerDateTimeType {
      static const int kMDY = 0; // m, d, y
      static const int kHM = 1; // hh, mm
      static const int kHMS = 2; // hh, mm, ss
      static const int kHM_AP = 3; // hh, mm, ap(AM/PM)
      static const int kMDYHM = 4; // m, d, y, hh, mm
      static const int kMDYHM_AP = 5; // m, d, y, hh, mm, AM/PM
      static const int kMDYHMS = 6; // m, d, y, hh, mm, ss
    
      static const int kYMD = 7; // y, m, d
      static const int kYMDHM = 8; // y, m, d, hh, mm
      static const int kYMDHMS = 9; // y, m, d, hh, mm, ss
      static const int kYMD_AP_HM = 10; // y, m, d, ap, hh, mm
    
      static const int kYM = 11; // y, m
      static const int kDMY = 12; // d, m, y
      static const int kY = 13; // y
      static const int kYQ = 14; //y,Q
      static const int kYMWD = 15; //y,m,w,d
    }
    
    class DateTimePickerAdapter extends PickerAdapter<DateTime> {
      /// display type, ref: columnType
      final int type;
    
      /// Whether to display the month in numerical form.If true, months is not used.
      final bool isNumberMonth;
    
      /// custom months strings
      final List<String> months;
    
      /// Custom AM, PM strings
      final List<String> strAMPM;
    
      /// year begin...end.
      final int yearBegin, yearEnd;
    
      /// minimum datetime
      final DateTime minValue, maxValue;
    
      /// jump minutes, user could select time in intervals of 30min, 5mins, etc....
      final int minuteInterval;
    
      /// Year, month, day suffix
      final String yearSuffix, monthSuffix, daySuffix, quarterSuffix, weekSuffix;
    
      /// use two-digit year, 2019, displayed as 19
      final bool twoDigitYear;
    
      /// year 0, month 1, day 2, hour 3, minute 4, sec 5, am/pm 6, hour-ap: 7
      final List<int> customColumnType;
    
      static const List<String> MonthsList_EN = const [
        "Jan",
        "Feb",
        "Mar",
        "Apr",
        "May",
        "Jun",
        "Jul",
        "Aug",
        "Sep",
        "Oct",
        "Nov",
        "Dec"
      ];
    
      static const List<String> MonthsList_EN_L = const [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December"
      ];
    
      DateTimePickerAdapter({
        Picker picker,
        this.type = 0,
        this.isNumberMonth = false,
        this.months = MonthsList_EN,
        this.strAMPM,
        this.yearBegin = 1900,
        this.yearEnd = 2100,
        this.value,
        this.minValue,
        this.maxValue,
        this.yearSuffix,
        this.monthSuffix,
        this.daySuffix,
        this.quarterSuffix,
        this.weekSuffix,
        this.minuteInterval,
        this.customColumnType,
        this.twoDigitYear = false,
      }) : assert(minuteInterval == null ||
                (minuteInterval >= 1 &&
                    minuteInterval <= 30 &&
                    (60 % minuteInterval == 0))) {
        super.picker = picker;
        _yearBegin = yearBegin;
        if (minValue != null && minValue.year > _yearBegin) {
          _yearBegin = minValue.year;
        }
      }
    
      int _col = 0;
      int _colAP = -1;
      int _yearBegin = 0;
    
      /// Currently selected value
      DateTime value;
    
      // but it can improve the performance, so keep it.
      static const List<List<int>> lengths = const [
        [12, 31, 0],
        [24, 60],
        [24, 60, 60],
        [12, 60, 2],
        [12, 31, 0, 24, 60],
        [12, 31, 0, 12, 60, 2],
        [12, 31, 0, 24, 60, 60],
        [0, 12, 31],
        [0, 12, 31, 24, 60],
        [0, 12, 31, 24, 60, 60],
        [0, 12, 31, 2, 12, 60],
        [0, 12],
        [31, 12, 0],
        [0],
        [0, 4],
        [0, 12, 52, 31],
      ];
    
      static const Map<int, int> columnTypeLength = {
        0: 0,
        1: 12,
        2: 31,
        3: 24,
        4: 60,
        5: 60,
        6: 2,
        7: 12,
        8: 4,
        9: 52,
      };
    
      /// year 0, month 1, day 2, hour 3, minute 4, sec 5, am/pm 6, hour-ap: 7
      static const List<List<int>> columnType = const [
        [1, 2, 0],
        [3, 4],
        [3, 4, 5],
        [7, 4, 6],
        [1, 2, 0, 3, 4],
        [1, 2, 0, 7, 4, 6],
        [1, 2, 0, 3, 4, 5],
        [0, 1, 2],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4, 5],
        [0, 1, 2, 6, 7, 4],
        [0, 1],
        [2, 1, 0],
        [0],
        [0, 8],
        [0, 1, 9, 2],
      ];
    
      // static const List<int> leapYearMonths = const <int>[1, 3, 5, 7, 8, 10, 12];
    
      // 获取当前列的类型
      int getColumnType(int index) {
        if (customColumnType != null) return customColumnType[index];
        List<int> items = columnType[type];
        if (index >= items.length) return -1;
        return items[index];
      }
    
      @override
      int getLength() {
        int v = customColumnType == null
            ? lengths[type][_col]
            : columnTypeLength[customColumnType[_col]];
        if (v == 0) {
          //
          int ye = yearEnd;
          if (maxValue != null) ye = maxValue.year;
          return ye - _yearBegin + 1;
        }
        //
        if (v == 31) return _calcDateCount(value.year, value.month);
    
        if (minuteInterval != null && minuteInterval > 1) {
          int _type = getColumnType(_col);
          if (_type == 4) {
            return v ~/ minuteInterval;
          }
        }
        //周,如果当年的12月31是周四,则当年有53周 (国际规定是周四为一周的第一天)
        if (v == 52) {
          DateTime date = DateTime.utc(value.year, 12, 31);
          if (date.weekday == DateTime.thursday) {
            return 53;
          }
        }
    
        return v;
      }
    
      @override
      int getMaxLevel() {
        return customColumnType == null
            ? lengths[type].length
            : customColumnType.length;
      }
    
      @override
      void setColumn(int index) {
        //print("setColumn index: $index");
        _col = index + 1;
        if (_col < 0) _col = 0;
      }
    
      @override
      void initSelects() {
        if (value == null) value = DateTime.now();
        _colAP = _getAPColIndex();
        int _maxLevel = getMaxLevel();
        if (picker.selecteds == null || picker.selecteds.length == 0) {
          if (picker.selecteds == null) picker.selecteds = List<int>();
          for (int i = 0; i < _maxLevel; i++) picker.selecteds.add(0);
        }
      }
    
      @override
      Widget buildItem(BuildContext context, int index) {
        String _text = "";
        int colType = getColumnType(_col);
        switch (colType) {
          case 0:
            if (twoDigitYear != null && twoDigitYear) {
              _text = "${_yearBegin + index}";
              var _l = _text.length;
              _text =
                  "${_text.substring(_l - (_l - 2), _l)}${_checkStr(yearSuffix)}";
            } else
              _text = "${_yearBegin + index}${_checkStr(yearSuffix)}";
            break;
          case 1:
            if (isNumberMonth) {
              _text = "${intToStr(index + 1)}${_checkStr(monthSuffix)}";
            } else {
              if (months != null)
                _text = "${intToStr(int.parse(months[index]))}";
              else {
    //            List _months =
    //                PickerLocalizations
    //                    .of(context)
    //                    .months ?? MonthsList_EN;
                List _months = MonthsList_EN;
                _text = "${intToStr(_months[index])}";
              }
            }
            break;
          case 2:
            _text = "${intToStr(index + 1)}${_checkStr(daySuffix)}";
            break;
          case 3:
          case 5:
            _text = "${intToStr(index)}";
            break;
          case 4:
            if (minuteInterval == null || minuteInterval < 2)
              _text = "${intToStr(index)}";
            else
              _text = "${intToStr(index * minuteInterval)}";
            break;
          case 6:
    //        List _ampm = strAMPM ?? PickerLocalizations
    //            .of(context)
    //            .ampm;
            List _ampm = strAMPM;
            if (_ampm == null) _ampm = const ['AM', 'PM'];
            _text = "${_ampm[index]}";
            break;
          case 7:
            _text = "${intToStr(index + 1)}";
            break;
          case 8:
            _text = "${_checkStr(quarterSuffix)}${index + 1}";
            break;
          case 9:
            _text = "${index + 1}${_checkStr(weekSuffix)}";
            break;
        }
    
        return makeText(null, _text, picker.selecteds[_col] == index);
      }
    
      @override
      String getText() {
        return value.toString();
      }
    
      @override
      int getColumnFlex(int column) {
        if (picker.columnFlex != null && column < picker.columnFlex.length)
          return picker.columnFlex[column];
        if (getColumnType(column) == 0) return 3;
        return 2;
      }
    
      @override
      void doShow() {
        if (_yearBegin == 0) getLength();
        var _maxLevel = getMaxLevel();
        for (int i = 0; i < _maxLevel; i++) {
          int colType = getColumnType(i);
          switch (colType) {
            case 0:
              picker.selecteds[i] = value.year - _yearBegin;
              break;
            case 1:
              picker.selecteds[i] = value.month - 1;
              break;
            case 2:
              picker.selecteds[i] = value.day - 1;
              break;
            case 3:
              picker.selecteds[i] = value.hour;
              break;
            case 4:
              picker.selecteds[i] = minuteInterval == null || minuteInterval < 2
                  ? value.minute
                  : value.minute ~/ minuteInterval;
              break;
            case 5:
              picker.selecteds[i] = value.second;
              break;
            case 6:
              picker.selecteds[i] = (value.hour > 12 || value.hour == 0) ? 1 : 0;
              break;
            case 7:
              picker.selecteds[i] = value.hour == 0
                  ? 11
                  : (value.hour > 12) ? value.hour - 12 - 1 : value.hour - 1;
              break;
            case 8:
              int quarter = getQuarter();
              picker.selecteds[i] = quarter - 1;
              break;
            case 9:
              int week = getWeek();
              picker.selecteds[i] = week - 1;
              break;
          }
        }
      }
    
      ///国际规定是周四为一周的第一天
      static const int EPOCH_WEEK_DAY = DateTime.thursday;
      static const int EPOCH_JULIAN_DAY = 0;
    
      int getWeek() {
        ///当前选中时间 周几
        var currentWeekDay = value.weekday;
    
        ///周四
        int EPOCH_WEEK_DAY = DateTime.thursday;
    
        DateTime epoch = DateTime.utc(value.year);
    
        int offset = EPOCH_WEEK_DAY - currentWeekDay;
    
        int delta = EPOCH_JULIAN_DAY - offset;
    
        int week = (value.difference(epoch).inDays - delta) ~/ 7 + 1;
        return week;
      }
    
      ///获取季度
      int getQuarter() {
        if (value.month >= 1 && value.month <= 3) {
          return 1;
        } else if (value.month >= 4 && value.month <= 6) {
          return 2;
        } else if (value.month >= 7 && value.month <= 9) {
          return 3;
        } else if (value.month >= 10 && value.month <= 12) {
          return 4;
        } else {
          return 0;
        }
      }
    
      @override
      void doSelect(int column, int index) {
        int year, month, day, h, m, s, q, w;
        year = value.year;
        month = value.month;
        day = value.day;
        h = value.hour;
        m = value.minute;
        s = value.second;
        q = getQuarter();
        w = getWeek();
        if (type != 2 && type != 6) s = 0;
        int colType = getColumnType(column);
        switch (colType) {
          case 0:
            year = _yearBegin + index;
            break;
          case 1:
            month = index + 1;
            break;
          case 2:
            day = index + 1;
            break;
          case 3:
            h = index;
            break;
          case 4:
            m = (minuteInterval == null || minuteInterval < 2)
                ? index
                : index * minuteInterval;
            break;
          case 5:
            s = index;
            break;
          case 6:
            if (picker.selecteds[_colAP] == 0) {
              if (h == 0) h = 12;
              if (h > 12) h = h - 12;
            } else {
              if (h < 12) h = h + 12;
              if (h == 12) h = 0;
            }
            break;
          case 7:
            h = index + 1;
            if (_colAP >= 0 && picker.selecteds[_colAP] == 1) h = h + 12;
            if (h > 23) h = 0;
            break;
          case 8:
            q = index + 1;
            if (q == 1) {
              month = 1;
            } else if (q == 2) {
              month = 4;
            } else if (q == 3) {
              month = 7;
            } else if (q == 4) {
              month = 10;
            }
            break;
          case 9:
            w = index + 1;
            break;
        }
        int __day = _calcDateCount(year, month);
        if (day > __day) day = __day;
        value = DateTime(year, month, day, h, m, s);
    
        if (minValue != null &&
            (value.millisecondsSinceEpoch < minValue.millisecondsSinceEpoch)) {
          value = minValue;
          notifyDataChanged();
        } else if (maxValue != null &&
            value.millisecondsSinceEpoch > maxValue.millisecondsSinceEpoch) {
          value = maxValue;
          notifyDataChanged();
        }
    
        ///年月周日类型,年或月或日改变的时候改动日期所在周也随之改变
        if (type == 15) {
          int selectWeek = getWeek();
          w = selectWeek - 1;
          notifyDataChanged();
        }
      }
    
      int _getAPColIndex() {
        List<int> items = customColumnType ?? columnType[type];
        for (int i = 0; i < items.length; i++) {
          if (items[i] == 6) return i;
        }
        return -1;
      }
    
      int _calcDateCount(int year, int month) {
        switch (month) {
          case 1:
          case 3:
          case 5:
          case 7:
          case 8:
          case 10:
          case 12:
            return 31;
          case 2:
            {
              if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
                return 29;
              }
              return 28;
            }
        }
        return 30;
      }
    
      String intToStr(int v) {
        return (v < 10) ? "0$v" : "$v";
      }
    
      String _checkStr(String v) {
        return v == null ? "" : v;
      }
    }
    
    class _StateView extends StatefulWidget {
      final WidgetBuilder builder;
    
      const _StateView({Key key, this.builder}) : super(key: key);
    
      @override
      State<StatefulWidget> createState() => _StateViewState();
    }
    
    class _StateViewState extends State<_StateView> {
      @override
      Widget build(BuildContext context) {
        return widget.builder(context);
      }
    
      update() {
        setState(() {});
      }
    }

    使用方法:

    DateTime showPickerDate = DateTime.now();
     int type;
        switch (timeFormat) {
    case 'yyyyMMdd': showPickerDate = DateTime.parse(dateParam); type = PickerDateTimeType.kYMD; break; case 'yyyyMM': type = PickerDateTimeType.kYM; showPickerDate = DateTime.parse(dateParam + '01'); break; case 'yyyy': type = PickerDateTimeType.kY; showPickerDate = DateTime.parse(dateParam + '0101'); break; case 'yyyyQM': type = PickerDateTimeType.kYQ; //季度转时间月份DateTime List quDateList = dateParam.split('Q'); showPickerDate = DateTime.parse( quDateList[0] + getMonthWithQuarter(quDateList[1]) + '01'); break; case 'yyyyWEEK': type = PickerDateTimeType.kYMWD; showPickerDate = DateTime.now(); break; } new Picker( height: 250, adapter: new DateTimePickerAdapter( type: type, isNumberMonth: true, yearSuffix: "", monthSuffix: "", daySuffix: "", quarterSuffix: "Q", weekSuffix: '', value: showPickerDate, ), title: new Text(S.of(context).datePicker_Title), onConfirm: (Picker picker, List value) { print(picker.adapter.text); }, onSelect: (Picker picker, int index, List<int> selecteds) { this.setState(() { stateText = picker.adapter.toString(); print(stateText); }); }).show(Scaffold.of(context));
    //根据季度获取时间月份
    String getMonthWithQuarter(String quarterString) {
    if (quarterString == '1') {
    return '01';
    } else if (quarterString == '2') {
    return '04';
    } else if (quarterString == '3') {
    return '07';
    } else if (quarterString == '4') {
    return '10';
    } else {
    return "";
    }
    }
     
  • 相关阅读:
    2016阿里巴巴73款开源产品全向图
    在微软5年,我学到的几个小技能
    2016 年 Java 工具和技术的调查:IDEA 已超过
    PHP学习总结(9)——PHP入门篇之WAMPServer服务控制面板介绍
    Template Pattern & Strategy Pattern
    天之道,损有余而补不足。人之道,则不然,损不足以奉有余。孰能有余以奉天下?唯有道者
    [林锐13]面向对象程序设计方法概述
    [林锐8.4]函数指针
    ZT c++ 中的重载全局new,delete
    ZT 自定义operator new与operator delete的使用(1)
  • 原文地址:https://www.cnblogs.com/lulushen/p/12869626.html
Copyright © 2011-2022 走看看