android 仿ios datepicker,Flutter 仿ios自定义一个DatePicker

87f7e676b73c

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 {

//年数组

List yearList = [];

//月数组

List monthList = [];

//天数组

List 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: [

_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 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 _getDayList({int year, int month}) {

List 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 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: [

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: [

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 _buildYearWidget() {

List 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 _buildMonthWidget() {

List 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 _buildDayWidget() {

List 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(

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);

},

);

});

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值