flutter自定义日期选择器按日、按月、自定义开始、结束时间

在这里插入图片描述在这里插入图片描述
导入包flutter_datetime_picker: 1.5.0
封装

import 'package:atui/jade/utils/JadeColors.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';class ATuiDateTimePickerDialog {static Future<DateTime> showDatePicker(BuildContext context, {bool showTitleActions: true,bool isShowDay: true,DateTime minTime,DateTime maxTime,DateChangedCallback onChanged,DateChangedCallback onConfirm,Function onCustomDateConfirm,DateCancelledCallback onCancel,locale: LocaleType.en,DateTime currentTime,DatePickerTheme theme,}) async {return await Navigator.push(context,_DatePickerRoute(showTitleActions: showTitleActions,onChanged: onChanged,onConfirm: onConfirm,onCustomDateConfirm: onCustomDateConfirm,onCancel: onCancel,locale: locale,theme: theme,isShowDay: isShowDay,barrierLabel:MaterialLocalizations.of(context).modalBarrierDismissLabel,pickerModel: DatePickerModel(currentTime: currentTime,maxTime: maxTime,minTime: minTime,locale: locale,),),);}
}class _DatePickerRoute<T> extends PopupRoute<T> {_DatePickerRoute({this.showTitleActions,this.onChanged,this.onConfirm,this.onCustomDateConfirm,this.onCancel,theme,this.barrierLabel,this.locale,this.isShowDay,RouteSettings settings,pickerModel,})  : this.pickerModel = pickerModel ?? DatePickerModel(),this.theme = theme ?? DatePickerTheme(),super(settings: settings);final bool showTitleActions;final DateChangedCallback onChanged;final DateChangedCallback onConfirm;final Function onCustomDateConfirm;final DateCancelledCallback onCancel;final DatePickerTheme theme;final LocaleType locale;final BasePickerModel pickerModel;final bool isShowDay;Duration get transitionDuration => const Duration(milliseconds: 200);bool get barrierDismissible => true;final String barrierLabel;Color get barrierColor => Colors.black54;AnimationController _animationController;AnimationController createAnimationController() {assert(_animationController == null);_animationController =BottomSheet.createAnimationController(navigator.overlay);return _animationController;}Widget buildPage(BuildContext context, Animation<double> animation,Animation<double> secondaryAnimation) {Widget bottomSheet = MediaQuery.removePadding(context: context,removeTop: true,child: _DatePickerComponent(onChanged: onChanged,locale: this.locale,route: this,pickerModel: pickerModel,isShowDay: isShowDay,),);return InheritedTheme.captureAll(context, bottomSheet);}
}class _DatePickerComponent extends StatefulWidget {_DatePickerComponent({Key key, this.route,this.onChanged,this.locale,this.pickerModel,this.isShowDay}): super(key: key);final DateChangedCallback onChanged;final _DatePickerRoute route;final LocaleType locale;final BasePickerModel pickerModel;bool isShowDay;State<StatefulWidget> createState() {return _DatePickerState();}
}class _DatePickerState extends State<_DatePickerComponent> {FixedExtentScrollController leftScrollCtrl, middleScrollCtrl, rightScrollCtrl;List<String> _btnTitleList = ['按日','按月','自定义'];int _selectPosition = 0;bool _isCustomTime = false;String _startDate;String _endDate = '结束时间';int _customDateType = 1; //1:开始时间 2:结束时间void initState() {super.initState();refreshScrollOffset();_startDate = '${widget.pickerModel.finalTime().year}/${widget.pickerModel.finalTime().month}/${widget.pickerModel.finalTime().day}';}void refreshScrollOffset() {
//    print('refreshScrollOffset ${widget.pickerModel.currentRightIndex()}');leftScrollCtrl = FixedExtentScrollController(initialItem: widget.pickerModel.currentLeftIndex());middleScrollCtrl = FixedExtentScrollController(initialItem: widget.pickerModel.currentMiddleIndex());rightScrollCtrl = FixedExtentScrollController(initialItem: widget.pickerModel.currentRightIndex());}Widget build(BuildContext context) {DatePickerTheme theme = widget.route.theme;return GestureDetector(child: AnimatedBuilder(animation: widget.route.animation,builder: (BuildContext context, Widget child) {final double bottomPadding = MediaQuery.of(context).padding.bottom;return ClipRect(child: CustomSingleChildLayout(delegate: _BottomPickerLayout(widget.route.animation.value,theme,showTitleActions: widget.route.showTitleActions,bottomPadding: bottomPadding,),child: GestureDetector(child: Material(color: theme.backgroundColor ?? Colors.white,shape: RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(15.0),topRight: Radius.circular(10.0)), // 设置圆角半径),child: _renderPickerView(theme)),),),);},),);}void _notifyDateChanged() {if (widget.onChanged != null) {widget.onChanged(widget.pickerModel.finalTime());}String _date = '${widget.pickerModel.finalTime().year}/${widget.pickerModel.finalTime().month}/${widget.pickerModel.finalTime().day}';if(_customDateType == 1){_startDate = _date;}else if(_customDateType == 2){_endDate = _date;}}Widget _renderPickerView(DatePickerTheme theme) {Widget itemView = _renderItemView(theme);return Column(children: <Widget>[if (widget.route.showTitleActions)_renderTitleActionsView(theme),_switchBtnView(),itemView,],);}Widget _renderColumnView(ValueKey key,DatePickerTheme theme,StringAtIndexCallBack stringAtIndexCB,ScrollController scrollController,int layoutProportion,ValueChanged<int> selectedChangedWhenScrolling,ValueChanged<int> selectedChangedWhenScrollEnd,) {return Expanded(flex: layoutProportion,child: Container(padding: EdgeInsets.all(8.0),height: theme.containerHeight,decoration: BoxDecoration(color: theme.backgroundColor ?? Colors.white),child: NotificationListener(onNotification: (ScrollNotification notification) {if (notification.depth == 0 &&selectedChangedWhenScrollEnd != null &&notification is ScrollEndNotification &&notification.metrics is FixedExtentMetrics) {final FixedExtentMetrics metrics = notification.metrics;final int currentItemIndex = metrics.itemIndex;selectedChangedWhenScrollEnd(currentItemIndex);}return false;},child: CupertinoPicker.builder(key: key,backgroundColor: theme.backgroundColor ?? Colors.white,scrollController: scrollController,itemExtent: theme.itemHeight,onSelectedItemChanged: (int index) {selectedChangedWhenScrolling(index);},useMagnifier: true,itemBuilder: (BuildContext context, int index) {final content = stringAtIndexCB(index);if (content == null) {return null;}return Container(height: theme.itemHeight,alignment: Alignment.center,child: Text(content,style: theme.itemStyle,textAlign: TextAlign.start,),);},),),),);}Widget _renderItemView(DatePickerTheme theme) {return Container(color: theme.backgroundColor ?? Colors.white,child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: <Widget>[Container(child: widget.pickerModel.layoutProportions()[0] > 0? _renderColumnView(ValueKey(widget.pickerModel.currentLeftIndex()),theme,widget.pickerModel.leftStringAtIndex,leftScrollCtrl,widget.pickerModel.layoutProportions()[0], (index) {widget.pickerModel.setLeftIndex(index);}, (index) {setState(() {refreshScrollOffset();_notifyDateChanged();});}): null,),Text(widget.pickerModel.leftDivider(),style: theme.itemStyle,),Container(child: widget.pickerModel.layoutProportions()[1] > 0? _renderColumnView(ValueKey(widget.pickerModel.currentLeftIndex()),theme,widget.pickerModel.middleStringAtIndex,middleScrollCtrl,widget.pickerModel.layoutProportions()[1], (index) {widget.pickerModel.setMiddleIndex(index);}, (index) {setState(() {refreshScrollOffset();_notifyDateChanged();});}): null,),Text(widget.pickerModel.rightDivider(),style: theme.itemStyle,),widget.isShowDay ?? true? Container(child: widget.pickerModel.layoutProportions()[2] > 0? _renderColumnView(ValueKey(widget.pickerModel.currentMiddleIndex() * 100 +widget.pickerModel.currentLeftIndex()),theme,widget.pickerModel.rightStringAtIndex,rightScrollCtrl,widget.pickerModel.layoutProportions()[2], (index) {widget.pickerModel.setRightIndex(index);}, (index) {setState(() {refreshScrollOffset();_notifyDateChanged();});}): null,): Container(),],),);}// Title ViewWidget _renderTitleActionsView(DatePickerTheme theme) {final done = _localeDone();final cancel = _localeCancel();return Container(height: theme.titleHeight,decoration: BoxDecoration(color: theme.headerColor ?? theme.backgroundColor ?? Colors.white,borderRadius: BorderRadius.only(topLeft: Radius.circular(15.0),topRight: Radius.circular(15.0))),child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: <Widget>[Container(height: theme.titleHeight,child: CupertinoButton(pressedOpacity: 0.3,padding: EdgeInsets.only(left: 16, top: 0),child: Text('$cancel',style: theme.cancelStyle,),onPressed: () {Navigator.pop(context);if (widget.route.onCancel != null) {widget.route.onCancel();}},),),Container(height: theme.titleHeight,child: CupertinoButton(pressedOpacity: 0.3,padding: EdgeInsets.only(right: 16, top: 0),child: Text('$done',style: theme.doneStyle,),onPressed: () {Navigator.pop(context, widget.pickerModel.finalTime());if (widget.route.onConfirm != null) {if(!_isCustomTime){widget.route.onConfirm(widget.pickerModel.finalTime());}else{widget.route.onCustomDateConfirm(_startDate,_endDate);}}},),),],),);}String _localeDone() {return i18nObjInLocale(widget.locale)['done'];}String _localeCancel() {return i18nObjInLocale(widget.locale)['cancel'];}//切换按钮Widget _switchBtnView(){return Container(height: 120.w,padding: EdgeInsets.symmetric(horizontal: 30.w),child: Column(children: [Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [Wrap(alignment: WrapAlignment.start,direction: Axis.horizontal,spacing: 30.w,textDirection: TextDirection.ltr,children: List.generate(_btnTitleList.length, (index) {return GestureDetector(child: Container(padding: EdgeInsets.only(left: 24.w,right: 24.w,top: 10.w,bottom: 12.w),decoration: BoxDecoration(color: _selectPosition == index ? JadeColors.yellow : JadeColors.lightGrey,borderRadius: BorderRadius.all(Radius.circular(20)),),child: Text(_btnTitleList[index],style: TextStyle(fontSize: 28.sp,color: _selectPosition == index ? JadeColors.grey_2 : JadeColors.grey),),),onTap: (){setState(() {_selectPosition = index;if(_selectPosition == 0){widget.isShowDay = true;_isCustomTime = false;}else if(_selectPosition == 1){widget.isShowDay = false;_isCustomTime = false;}else if(_selectPosition == 2){widget.isShowDay = true;_isCustomTime = true;}});},);})),GestureDetector(child: Container(padding: EdgeInsets.only(left: 20.w,right: 20.w,top: 10.w,bottom: 10.w),decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(20),border: Border.all(width: 1.w,color: JadeColors.grey_2)),child: Text('清除筛选',style: TextStyle(fontSize: 28.sp,color: JadeColors.grey_2),),),)],),_customDataSelectView()],),);}_customDataSelectView(){return _isCustomTime?Container(margin: EdgeInsets.only(top: 15.w),child: Row(mainAxisAlignment: MainAxisAlignment.center,children: [GestureDetector(child: Column(children: [IntrinsicWidth(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text("$_startDate",style: TextStyle(overflow: TextOverflow.fade, color: _customDateType == 1?JadeColors.red_6 : JadeColors.grey_7, fontSize: 30.sp),),Container(margin: EdgeInsets.only(top: 1.h),height: 1,color: _customDateType == 1?JadeColors.red_6 : JadeColors.grey_7,)],),),]),onTap: () {setState(() {_customDateType = 1;});}),Container(width: 30.w, height: 1, color: JadeColors.grey_7, margin: EdgeInsets.symmetric(horizontal: 40.w)),GestureDetector(child: Column(children: [IntrinsicWidth(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text("$_endDate",style: TextStyle(overflow: TextOverflow.fade, color: _customDateType == 2?JadeColors.red_6 : JadeColors.grey_7, fontSize: 30.sp),),Container(margin: EdgeInsets.only(top: 1.h),height: 1,color: _customDateType == 2?JadeColors.red_6 : JadeColors.grey_7,)],),),]),onTap: () {setState(() {_customDateType = 2;});})],),):Container();}}class _BottomPickerLayout extends SingleChildLayoutDelegate {_BottomPickerLayout(this.progress,this.theme, {this.itemCount,this.showTitleActions,this.bottomPadding = 0,});final double progress;final int itemCount;final bool showTitleActions;final DatePickerTheme theme;final double bottomPadding;BoxConstraints getConstraintsForChild(BoxConstraints constraints) {double maxHeight = theme.containerHeight;if (showTitleActions) {maxHeight += theme.titleHeight + 120.w;//增加actionTitle布局(取消、确定)时和切换按钮的布局时要在当前的布局高度上再加上去}return BoxConstraints(minWidth: constraints.maxWidth,maxWidth: constraints.maxWidth,minHeight: 0.0,maxHeight: maxHeight + bottomPadding,);}Offset getPositionForChild(Size size, Size childSize) {final height = size.height - childSize.height * progress;return Offset(0.0, height);}bool shouldRelayout(_BottomPickerLayout oldDelegate) {return progress != oldDelegate.progress;}
}

引用

_dateFilter() async {LocaleType localeType;await ATuiSharedPreferences.getStorage("localType").then((value) {if (value == "zh") {localeType = LocaleType.zh;} else if (value == "en") {localeType = LocaleType.en;}});ATuiDateTimePickerDialog.showDatePicker(context,//isShowDay: false,locale: localeType ?? LocaleType.zh,theme: DatePickerTheme(cancelStyle: TextStyle(fontSize: 30.sp,color: JadeColors.grey_2),doneStyle: TextStyle(fontSize: 30.sp,color: JadeColors.grey_2,fontWeight: FontWeight.w600)),onConfirm: (datetime) async {String newDate = '${datetime.year}-${datetime.month}-${datetime.day}';newDate += datetime.month < 10? '0${datetime.month}': datetime.month.toString();print('非自定义时点击确定按钮= $newDate');},onCustomDateConfirm: (startDatetime,endDatetime) async {print('自定义时点击确定按钮');print('startDatetime= $startDatetime');print('endDatetime= $endDatetime');},onChanged: (datetime) {print('onChanged dateTime: ${datetime}');},);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/10830.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

景源畅信电商:经营抖店需要电脑吗?

经营抖店是否需要电脑?这个问题看似简单&#xff0c;实则关乎着商家的运营效率和成本投入。在当前数字化、网络化的商业环境中&#xff0c;电脑已经成为了不可或缺的工具。那么&#xff0c;经营抖店究竟是否需要电脑呢?答案是肯定的。 一、高效处理订单 电脑能够高效地处理大…

如何在湖师大官网找到考研真题

今天学弟问我怎么找真题&#xff0c;我必须告诉他怎么找湖师大的真题&#xff0c;身为考研学子&#xff0c;这是必须要知道滴&#xff0c;尤其是自命题&#xff0c;是吧&#xff0c;话不多说&#xff0c;言归正传&#xff0c;我们开始吧&#xff01; 1 打开湖师大官网 什么&a…

树莓派nmap扫描

debian系统安装nmap&#xff1a; sudo apt install nmap安装nmap完成后&#xff0c;输入 ip route 来查看当前Wi-Fi路由器的ip地址。 第一行的default via后显示的便是网关地址&#xff0c;也就是路由器地址。 获取到路由器ip地址后&#xff0c;在终端中输入&#xff1a; …

一站式HMI软件开发套件eStation,让开发更简单高效

4月份举办的北京国际车展上全球首发车117辆&#xff0c;新能源车型278个&#xff0c;越来越多的车厂通过差异化和改善UI/UE体验&#xff0c;来获取更多用户的青睐。为快速响应差异化竞争需求&#xff0c;智能座舱HMI市场遇到以下挑战&#xff1a; 如何兼容不同项目开发人员编程…

力扣例题(用栈实现队列)

目录 链接. - 力扣&#xff08;LeetCode&#xff09; 描述 思路 push pop peek empty 代码 链接. - 力扣&#xff08;LeetCode&#xff09; 描述 思路 push 例如我们将10个元素放入栈中&#xff0c;假设最左边为栈顶&#xff0c;最右侧为栈底 则为10,9,8,7,6,5,4,3,…

嵌入式 - GPIO编程简介

An Introduction to GPIO Programming By Jeff Tranter Wednesday, June 12, 2019 编者按&#xff1a;本 2019 年博客系列是 ICS 最受欢迎的系列之一&#xff0c;现已更新&#xff08;2022 年 12 月&#xff09;&#xff0c;以确保内容仍然准确、相关和有用。 本博客是 Integr…

图片转word如何转换?

要将图片转换为Word文档&#xff0c;你可以使用以下方法之一&#xff1a; 以上这些方法都可以帮助你将图片中的文本转换为可编辑的Word文档&#xff0c;你可以根据自己的喜好和需求选择其中一种方法来操作。 使用OCR软件或在线工具&#xff1a;有许多OCR&#xff08;Optical Ch…

电子资源|基于SSM+vue的电子资源管理系统(源码+数据库+文档)​

电子资源管理系统 目录 基于SSMvue的电子资源管理系统 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 5.2.1管理员功能模块 5.2.2用户功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&am…

【Qt 学习笔记】Qt常用控件 | 多元素控件 | Tree Widget的说明及介绍

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 多元素控件 | Tree Widget的说明及介绍 文章编号&#x…

python代码实现TF-IDF

1、TF-IDF解释 TF-IDF&#xff08;Term frequency–inverse document frequency&#xff09;&#xff0c;中文翻译就是词频 - 逆文档频率&#xff0c;是一种用来计算关键词的传统方法。 TF&#xff08;Term Frequency&#xff09;&#xff1a;TF 的意思就是词频&#xff0c;是…

SQL Server共享功能目录显示灰色无法自行选择

SQL Server共享功能目录显示灰色无法自行调整 一、 将之前安装SQL Server卸载干净 二、 清空注册表 1. 打开注册表&#xff0c;winR&#xff0c;输入regedit 2. 注册表-》编辑-》查找&#xff0c;输入C:\Program Files\Microsoft SQL Server\ 3. 注册表-》编辑-》查找&#x…

docker+nginx+Jenkins自动构建

文章目录 前言一、实操记录问下AI&#xff1a;jenkins 配置新增一个mobilegit配置Build TriggersBuild EnvironmentBuild StepsPost-build Actions 上面一顿配置下来&#xff0c;构建 -- FAILURE 总结 前言 在已有docker-Jenkins-nginx 部署方案上&#xff0c;在另外一台测试…

C++实现一个简单的控制cpu利用率的程序

写一个程序&#xff0c;让控制cpu利用率在20%左右 思路很简单&#xff1a;每个循环控制sleep的时间占比 #include <iostream> #include <chrono> #include <unistd.h>int main() {int ratio 20;int base_time 1000;int sleeptime base_time * (100-ratio…

【计算机网络篇】数据链路层(10)在物理层扩展以太网

文章目录 &#x1f354;扩展站点与集线器之间的距离&#x1f6f8;扩展共享式以太网的覆盖范围和站点数量 &#x1f354;扩展站点与集线器之间的距离 &#x1f6f8;扩展共享式以太网的覆盖范围和站点数量 以太网集线器一般具有8~32个接口&#xff0c;如果要连接的站点数量超过了…

10分钟入门pandas(一)

pandas 是基于python语言的数据分析处理库,使用广泛。本文主要参考pandas的官方入门指导,并结合自己入门使用的一些常用操作进行说明。 pandas通常和numpy结合使用,一般通过如下语句导入numpy和pandas库。 import numpy as np import pandas as pd一. pandas 数据结构 pan…

基于SSM的计算机课程实验管理系统的设计与实现(源码)

| 博主介绍&#xff1a;✌程序员徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f44…

大屏分辨率适配插件v-scale-screen

前言&#xff1a;大屏分辨率适配繁多&#xff0c;目前我认为最简单且问题最少的的方案就是使用v-scale-screen插件&#xff0c;无需考虑单位转换&#xff0c;position定位也正常使用。 1. 效果 填充满屏幕的效果 保持宽高比的效果 2. 插件原理 原理是通过css transfom 实现…

macOS12安装 php8.1和apache

1. 安装php 8.1 macOS12不再自带php brew tap shivammathur/php 查看可安装版本 brew search php 安装指定版本 brew install php8.1 环境配置 vim ~/.zshrc export PATH"/usr/local/opt/php8.1/bin:$PATH" export PATH"/usr/local/opt/php8.1/sbin:$PAT…

[C#] 使用HttpClient请求https地址报错的解决方案

当使用HttpClient请求HTTPS地址遇到报错时&#xff0c;下面将解析并提供可能的解决方案供参考。 文章目录 异常代码无法定位错误的准确定位错误的 常见错误错误1错误2 解决问题生产环境开发环境 异常代码 首先&#xff0c;需要查看引发异常的代码部分, 无法定位错误的 以下代…

Android Compose 一:基础控件

Flutter 与 Compose 组件辣么像&#xff0c;难道是同一个google团队整的&#xff1b;也未深究&#xff0c;只是猜测。 创建项目 需要使用新版本Android studio&#xff0c;忽略步骤… 项目目录 MainActivity说明 1 系统默认页面 Preview 修饰的方法&#xff0c;只用来供开发…