Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Flutter 仿ios自定义一个DatePicker

Flutter 仿ios自定义一个DatePicker

作者头像
赵哥窟
发布于 2021-03-02 06:32:36
发布于 2021-03-02 06:32:36
1.1K00
代码可运行
举报
文章被收录于专栏:日常技术分享日常技术分享
运行总次数:0
代码可运行

Screenshot_1612747215.png

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
遭遇DDoS攻击怎么防?
导语| 最近几个月处理过多起DDoS攻击案例,从实际案例中总结了一些防护经验希望可以帮助到需要的同仁。本文主要分享DDoS攻击原理、以及实际攻击过程以及如何选择DDoS防护方案。
binwenli
2020/10/11
14.6K4
遭遇DDoS攻击怎么防?
轻量应用服务器 Lighthouse 隔离后快速恢复业务教程
如果轻量服务器突然被DDoS攻击,腾讯云的轻量云轻量服务器默认自带2G的防护。但是根据现在的常规攻击情况,基本只要被打,一下就会挂了。腾讯云的DDoS防护机制为:只要被攻击,超过了防护值2Gbps,就会将主机的IP进行隔离,也就是外网访问不了,类似于关进小黑屋。当攻击停止后,服务器提供自助解封3次。如果服务器被攻击短暂隔离解封次数超过3次后,服务器将会进入隔离24小时的状态。
腾云工具人
2024/09/25
4420
腾讯云服务器宙斯盾安全防护相关概念及安全产品概述
腾讯云宙斯盾安全防护(Aegis Anti-DDoS)基于腾讯海量业务十余年安全技术积累,为业务提供多层级全方位、高性价比的应对 DDoS 攻击威胁的防护方案,能够对各类网络攻击流量进行精准清洗,并将正常业务流量回送到业务服务器,防止 DDoS 攻击造成业务波动、服务中断、用户体验劣化等问题。同时,宙斯盾安全防护具备 T 级防护资源和专属防护集群,并可通过自定义高级安全策略,对特定攻击行为进行针对性防护。
用户5915142
2019/09/11
6.3K0
腾讯云服务器宙斯盾安全防护相关概念及安全产品概述
云服务器cvm快速入门教程
本文主要介绍快速配置云服务器的方法。若快速配置不能满足您的需求,您可参考 自定义配置 Linux 云服务器 文档进行配置。
勤劳的小蜜蜂
2019/08/25
3.5K0
云服务器是什么?ECS、BCC、CVM...
云服务器是一种简单高效、处理能力可弹性伸缩的计算服务,帮助用户快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本,使用户更专注于核心业务创新。
用户7426861
2021/08/24
25.1K0
【最佳实践】巡检项:DDoS 防护可用 IP 黑洞解封次数与被封堵的公网IP检查
当目标 IP 受到的攻击流量超过其封堵阈值时,腾讯云将通过运营商的服务屏蔽该 IP 的所有外网访问,保护云平台其他用户免受影响。简而言之,当您的某个 IP 受到的攻击流量超过当前地域腾讯云最大防护能力时,腾讯云将屏蔽该 IP 的所有外网访问。
熊昪
2022/04/01
1.2K0
腾讯云国际版:云服务器功能与优势
多地域多可用区:掩盖我国、亚太、欧洲及美洲下的多个地域。在接近您用户的地域布置运用可获得较低的时延。
老鹰飞机@laoying06
2023/07/01
8900
腾讯云国际版:云服务器功能与优势
解决云服务器被攻击至黑洞状态的实战指南
当云服务器遭遇大规模的DDoS攻击时,为了保护网络基础设施和其他客户的服务不受影响,云服务提供商通常会将受到攻击的服务器置于所谓的“黑洞”状态——即完全屏蔽其对外的所有网络连接。本文将详细介绍云服务器被攻击至黑洞状态的原因、识别方法以及解决策略。
群联云安全小杜
2024/08/28
4300
解决云服务器被攻击至黑洞状态的实战指南
玩转CVM之外网不通排查
在用户使用CVM的过程中,经常会出现访问外网不通的情况。外网不通的原因从平台到系统都有可能会出现,在排查的时候涉及的方面有很多。基于此,本文提供详细的排查思路帮助各位解决类似的问题。
苏欣
2019/07/23
19K0
腾讯云双十一福利篇之CVM云服务器
云服务器 CVM 支持用户自定义一切资源:CPU、内存、硬盘、网络、安全等,并可以在需求发生变化时轻松地调整它们。
小馒头学Python
2024/11/13
4910
腾讯云双十一福利篇之CVM云服务器
手把手教学!教你3步高效配置云服务器(windows/Linux版)
如果你是首次使用云服务器,建议你先选择轻量应用服务器(Lighthouse) 来作为云服务器使用的入门途径。
腾讯产业互联网学堂1
2023/09/04
8620
手把手教学!教你3步高效配置云服务器(windows/Linux版)
腾讯云轻量应用服务器分配唯一的独立的公网IP地址吗?
是的,​腾讯云轻量应用服务器默认会分配一个独立的公网IPv4地址,且该IP地址为独享​,你一个人使用的(非共享IP),用户可完全自主使用。以下是关键细节解析:
用户11543454
2025/04/02
2700
【如何快速上手腾讯云?】云服务器CVM快速入门教程(一)
文档中心 》云服务器 》快速入门》快速配置》 快速入门 Windows 云服务器
勤劳的小蜜蜂
2019/07/02
2.7K0
腾讯大禹 DDoS防护方案
通过分布在各地的大量终端,同时向目标发送恶意报包,以阻塞被打击目标的出口带宽,或耗尽被打击目标的CPU资源,最终使被打击目标服务瘫痪。举一个形象易懂的面馆例子:
腾讯云开发者社区
2018/08/01
12.7K0
腾讯大禹 DDoS防护方案
快速入门 Linux 云服务器
如果是首次购买和使用云服务器实例的个人用户,推荐按照本文介绍的流程快速配置、购买和连接实例。
云服务器教程
2019/04/10
3.8K0
快速入门 Linux 云服务器
云主机对比-腾讯云服务器的优势优点有哪些
腾讯云服务器优势优点有哪些?很多朋友在购买云服务器时,会看到腾讯云服务器的品牌,但是对腾讯云的特点缺乏一定的了解,这里我们介绍下腾讯云服务器优势优点有哪些。
tengxunyun8点com活动整理
2019/04/09
42.1K1
云主机对比-腾讯云服务器的优势优点有哪些
腾讯云-云服务器概述&售前
云服务器(Cloud Virtual Machine , CVM)提供安全可靠的弹性计算服务,只需要几分钟,可以在云端获取和启动CVM实现你的计算需求,随着业务的需求变化, 你可以实时扩展或者缩减计算资源,CVM 支持按实际使用的资源计费,可以节约计算成本,使用CVM 可以极大降低软硬件的采购成本,简化IT运维工作。
Chris Fei
2021/05/03
39.9K0
【腾讯云产品最佳实践】腾讯云服务器CVM安装与配置及实际使用
双十一活动入口:https://cloud.tencent.com/act/pro/double11-2024?fromSource=gwzcw.8891746.8891746.8891746
三掌柜
2024/11/18
3450
【腾讯云产品最佳实践】腾讯云服务器CVM安装与配置及实际使用
腾讯云服务器与普通服务器区别在哪?如何选择?
腾讯云服务器与普通的IDC机房或服务器厂商相比,腾讯云服务器CVM具有高可用性、安全性和弹性优势。小编从以上几个方面详细说下这二者的区别及如何选择。
用户5916283
2019/09/19
8K0
腾讯云服务器与普通服务器区别在哪?如何选择?
腾讯云服务器有什么优势?稳定性怎么样?
先为大家带来一点福利。腾讯云最近开始发放代金券了,新客户无门槛领取总价值高达2775元代金券,每种代金券限量500张,先到先得,建议大家都领取一份,反正是免费领的,说不定以后需要呢?
用户5601883
2019/07/16
11.1K0
腾讯云服务器有什么优势?稳定性怎么样?
推荐阅读
相关推荐
遭遇DDoS攻击怎么防?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验