美文网首页
Flutter 仿ios自定义一个DatePicker

Flutter 仿ios自定义一个DatePicker

作者: 赵哥窟 | 来源:发表于2021-02-08 09:24 被阅读0次
    Screenshot_1612747215.png

    编辑个人资料,修改生日的时候需要用到,需求就是如果传了日期就要滚动到传的日期位置,如果没有穿就是系统当前时间。所以动手撸一个,有需要的同学可以拿去做轮子。

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_screenutil/screenutil.dart';
    import 'package:toofoo/common/color/colorsUtil.dart';
    
    typedef OnSelectedDate = void Function(String date);
    
    class DatePicker extends StatefulWidget {
      DatePicker(
          {this.onSelectedDate,
          this.selectedDate,
          this.startYear = 1970,
          this.endYear = 2500});
    
      // 结果返回
      final OnSelectedDate onSelectedDate;
      final String selectedDate; //选中的时间
      final int startYear;
      final int endYear;
    
      @override
      _DatePickerState createState() => _DatePickerState();
    }
    
    class _DatePickerState extends State<DatePicker> {
      //年数组
      List<String> yearList = [];
      //月数组
      List<String> monthList = [];
      //天数组
      List<String> dayList = [];
      //年的索引
      int yearIndex;
      //月的索引
      int monthIndex;
      //天的索引
      int dayIndex;
      //每列的宽度
      double _columnWidth;
    
      FixedExtentScrollController yearScrollController;
      FixedExtentScrollController monthScrollController;
      FixedExtentScrollController dayScrollController;
    
      @override
      void initState() {
        super.initState();
    
        _columnWidth = ScreenUtil.screenWidth / 3;
    
        _setupData();
    
        _initSelectedIndex();
      }
    
      @override
      void dispose() {
        yearScrollController.dispose();
        monthScrollController.dispose();
        dayScrollController.dispose();
    
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              _headerWidget(),
              _datePicker(),
            ],
          ),
        );
      }
    
      ///初始化数据
      void _setupData() {
        for (int i = widget.startYear; i <= widget.endYear; i++) {
          yearList.add(i.toString());
        }
    
        for (int i = 1; i <= 12; i++) {
          monthList.add(i.toString().padLeft(2, '0'));
        }
    
        // 初始化天数(当前时间系统时间的天数)
        int year = DateTime.now().year;
        int month;
        if (widget.selectedDate == null || widget.selectedDate.isEmpty) {
          month = DateTime.now().month;
        } else {
          List<String> date = widget.selectedDate.split('-');
          month = int.parse(date[1]);
        }
    
        dayList = _getDayList(year: year, month: month);
      }
    
      int _getDayCount({int year, int month}) {
        int dayCount = DateTime(year, month + 1, 0).day;
        return dayCount;
      }
    
      List<String> _getDayList({int year, int month}) {
        List<String> dayList = [];
        int days = _getDayCount(year: year, month: month);
        for (int i = 1; i <= days; i++) {
          dayList.add(i.toString().padLeft(2, '0'));
        }
    
        return dayList;
      }
    
      ///选中年月后更新天
      void _updateDayList() {
        int year = int.parse(yearList[yearIndex]);
        int month = int.parse(monthList[monthIndex]);
    
        setState(() {
          dayIndex = 0;
          dayList = _getDayList(year: year, month: month);
    
          if (dayScrollController.positions.length > 0) {
            dayScrollController.jumpTo(0);
          }
        });
      }
    
      ///初始化时间索引
      void _initSelectedIndex() {
        final List uniqueYearList = Set.from(yearList).toList();
        final List uniqueMonthList = Set.from(monthList).toList();
        final List uniqueDayList = Set.from(dayList).toList();
    
        ///获取索引
        if (widget.selectedDate != null && widget.selectedDate.isNotEmpty) {
          ///传了选中日期的时候
          List<String> date = widget.selectedDate.split('-');
    
         setState(() {
           yearIndex = uniqueYearList.indexOf(date[0]);
           monthIndex = uniqueMonthList.indexOf(date[1]);
           dayIndex = uniqueDayList.indexOf(date[2]);
         });
        } else {
          ///没有传选中日期默认当前系统时间
          String year = DateTime.now().year.toString();
          String month = DateTime.now().month.toString().padLeft(2, '0');
          String day = DateTime.now().day.toString().padLeft(2, '0');
    
         setState(() {
           yearIndex = uniqueYearList.indexOf(year);
           monthIndex = uniqueMonthList.indexOf(month);
           dayIndex = uniqueDayList.indexOf(day);
         });
        }
    
        yearScrollController = FixedExtentScrollController(initialItem: yearIndex);
        monthScrollController =
            FixedExtentScrollController(initialItem: monthIndex);
        dayScrollController = FixedExtentScrollController(initialItem: dayIndex);
      }
    
      Widget _headerWidget() {
        return Container(
          height: 60,
          child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                FlatButton(
                  child: Text(
                    '取消',
                    style: TextStyle(
                      fontSize: 16.0,
                    ),
                  ),
                  onPressed: () {
                    Navigator.pop(context);
                  },
                ),
                FlatButton(
                  child: Text(
                    '确定',
                    style: TextStyle(
                      fontSize: 16.0,
                    ),
                  ),
                  onPressed: () {
                    if (widget.onSelectedDate != null) {
                      String date = yearList[yearIndex]+'-'+monthList[monthIndex]+'-'+dayList[dayIndex];
                      widget.onSelectedDate(date);
                    }
                  },
                ),
              ]),
          decoration: BoxDecoration(
            border: Border(
                bottom: BorderSide(color: Colors.grey.withOpacity(0.1), width: 1)),
          ),
        );
      }
    
      Widget _datePicker() {
        return Container(
          color: Colors.white,
          height: 200,
          child: Stack(
            children: [
              Row(
                children: <Widget>[
                  Expanded(child: _yearPickerView()),
                  Expanded(child: _monthPickerView()),
                  Expanded(child: _dayPickerView()),
                ],
              ),
              Container(
                color: ColorsUtil.hexStringColor('D1D1D6'),
                margin: EdgeInsets.only(top: 78),
                height: 1,
              ),
              Container(
                color: ColorsUtil.hexStringColor('D1D1D6'),
                margin: EdgeInsets.only(top: 124),
                height: 1,
              ),
              Container(
                margin: EdgeInsets.only(top: 78),
                child: Row(
                  children: [
                    Expanded(
                      child: Padding(
                        padding: EdgeInsets.only(left: _columnWidth - 40, top: 9),
                        child: Text(
                          '年',
                          style: TextStyle(color: Colors.grey, fontSize: 16),
                          maxLines: 1,
                        ),
                      ),
                    ),
                    Expanded(
                      child: Padding(
                        padding: EdgeInsets.only(left: _columnWidth - 50, top: 9),
                        child: Text(
                          '月',
                          style: TextStyle(color: Colors.grey, fontSize: 16),
                          maxLines: 1,
                        ),
                      ),
                    ),
                    Expanded(
                      child: Padding(
                        padding: EdgeInsets.only(left: _columnWidth - 50, top: 9),
                        child: Text(
                          '日',
                          style: TextStyle(color: Colors.grey, fontSize: 16),
                          maxLines: 1,
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        );
      }
    
      ///年
      Widget _yearPickerView() {
        return Container(
          child: CupertinoPicker(
            scrollController: yearScrollController,
            children: _buildYearWidget(),
            looping: true,
            selectionOverlay: Center(),
            onSelectedItemChanged: (index) {
              setState(() {
                yearIndex = index;
              });
              _updateDayList();
            },
            itemExtent: 44,
          ),
        );
      }
    
      ///月
      Widget _monthPickerView() {
        return Container(
          child: CupertinoPicker(
            scrollController: monthScrollController,
            children: _buildMonthWidget(),
            looping: true,
            selectionOverlay: Center(),
            onSelectedItemChanged: (index) {
              setState(() {
                monthIndex = index;
              });
              _updateDayList();
            },
            itemExtent: 44,
          ),
        );
      }
    
      ///日
      Widget _dayPickerView() {
        return Container(
          child: CupertinoPicker(
            scrollController: dayScrollController,
            children: _buildDayWidget(),
            looping: true,
            selectionOverlay: Center(),
            onSelectedItemChanged: (index) {
              setState(() {
                dayIndex = index;
              });
            },
            itemExtent: 44,
          ),
        );
      }
    
      ///年Widget
      List<Widget> _buildYearWidget() {
        List<Widget> yearListWidget = []; //先建一个数组用于存放循环生成的widget
        Widget content; //单独一个widget组件,用于返回需要生成的内容widget
        for (var item in yearList) {
          yearListWidget.add(
            new Center(
              child: Text(
                item,
                style: TextStyle(color: Colors.black87, fontSize: 16),
                maxLines: 1,
              ),
            ),
          );
        }
    
        return yearListWidget;
      }
    
      ///月Widget
      List<Widget> _buildMonthWidget() {
        List<Widget> monthListWidget = []; //先建一个数组用于存放循环生成的widget
        Widget content; //单独一个widget组件,用于返回需要生成的内容widget
        for (var item in monthList) {
          monthListWidget.add(
            new Center(
              child: Text(
                item,
                style: TextStyle(color: Colors.black87, fontSize: 16),
                maxLines: 1,
              ),
            ),
          );
        }
    
        return monthListWidget;
      }
    
      ///日Widget
      List<Widget> _buildDayWidget() {
        List<Widget> dayListWidget = []; //先建一个数组用于存放循环生成的widget
        Widget content; //单独一个widget组件,用于返回需要生成的内容widget
        for (var item in dayList) {
          dayListWidget.add(
            new Center(
              child: Text(
                item,
                style: TextStyle(color: Colors.black87, fontSize: 16),
                maxLines: 1,
              ),
            ),
          );
        }
    
        return dayListWidget;
      }
    }
    
    

    使用

    void _showBirthdayDialog(BuildContext context, Dispatch dispatch) {
      showModalBottomSheet<void>(
          context: context,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(20),
              topRight: Radius.circular(20),
            ),
          ),
          builder: (BuildContext context) {
            return DatePicker(
              endYear: DateTime.now().year,
              selectedDate: null,
              onSelectedDate: (String date) {
                Navigator.pop(context);
              },
            );
          });
    }
    

    相关文章

      网友评论

          本文标题:Flutter 仿ios自定义一个DatePicker

          本文链接:https://www.haomeiwen.com/subject/ekjxxltx.html