前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter 仿ios自定义一个DatePicker

Flutter 仿ios自定义一个DatePicker

作者头像
赵哥窟
发布2021-03-02 14:32:36
9340
发布2021-03-02 14:32:36
举报
文章被收录于专栏:日常技术分享日常技术分享

Screenshot_1612747215.png

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

代码语言:javascript
复制
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;
  }
}

使用

代码语言:javascript
复制
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);
          },
        );
      });
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档