首先看下效果
颜色文件和屏幕适配的文件 可以自己给定
import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_xiaoe/utils/ScreenUtil.dart';
import 'package:flutter/material.dart';
import 'package:flutter_xiaoe/utils/TimeUtil.dart';
import 'package:flutter_xiaoe/widgets/common/calendar/DayGridView.dart';
import 'package:flutter_xiaoe/config/Colors.dart';
class Calendar extends StatefulWidget {
DateTime initTime;
DateTime firstTime;
DateTime endTime;
ValueChanged onChange;
Calendar({
Key key,
this.initTime,
this.firstTime,
this.endTime,
this.onChange,
}) : super(key: key);
@override
State<Calendar> createState() => _CalendarState();
}
class _CalendarState extends State<Calendar> {
PageController pageController;
DateTime selectDate;
int initPage = 0;
int totalPage = 0;
@override
void initState() {
super.initState();
print(widget.firstTime.month);
selectDate = widget.initTime;
/// 总共的月份数目
totalPage = (widget.endTime.year - widget.firstTime.year == 0
? widget.endTime.month
: ((widget.endTime.year - widget.firstTime.year) * 12 +
widget.endTime.month -
widget.firstTime.month +
1));
/// 当前月份处于
initPage = (widget.initTime.year - widget.firstTime.year == 0
? widget.initTime.month
: ((widget.initTime.year - widget.firstTime.year) * 12 +
widget.initTime.month -
widget.firstTime.month +
1));
print(totalPage);
print(initPage);
pageController = PageController(
initialPage: totalPage,
);
}
onChange(time) {
if (selectDate != time) {
setState(() {
selectDate = time;
widget.onChange(time);
});
}
}
@override
Widget build(BuildContext context) {
return Column(children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: TimeUtil.getDayHeaders(MaterialLocalizations.of(context)),
),
Container(
color: AppColors.WHITE,
height: ScreenUtil.px2pt(600),
child: PageView.builder(
itemBuilder: (BuildContext context, int index) {
return DayGridView(
initDate: DateTime(widget.initTime.year, widget.initTime.month,
widget.initTime.day),
selectDate:
DateTime(selectDate.year, selectDate.month, selectDate.day),
year: widget.firstTime.year +
((widget.firstTime.month + index - 1) / 12).floor(),
month: (widget.firstTime.month + index) % 12 == 0
? 12
: (widget.firstTime.month + index) % 12,
onChange: onChange,
);
},
itemCount: totalPage,
controller: pageController,
),
),
]);
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_xiaoe/utils/ScreenUtil.dart';
import 'package:flutter_xiaoe/utils/NetUtil.dart';
import 'package:flutter_xiaoe/config/Api.dart';
import 'package:flutter_xiaoe/config/Colors.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'package:flutter_xiaoe/utils/TimeUtil.dart';
class DayGridView extends StatefulWidget {
DateTime initDate;
DateTime selectDate;
int year;
int month;
ValueChanged onChange;
DayGridView({
Key key,
@required this.initDate,
@required this.selectDate,
@required this.year,
@required this.month,
this.onChange,
});
@override
State<DayGridView> createState() => _DayGridViewState();
}
class _DayGridViewState extends State<DayGridView> {
@override
void initState() {
super.initState();
}
List<Widget> dayItems() {
List days = TimeUtil.getDay(
widget.year, widget.month, MaterialLocalizations.of(context));
List dayWidgets = days.map((value) {
if (value is int) {
return Container();
}
if (value == widget.selectDate) {
return GestureDetector(
onTap: () {
widget.onChange(widget.selectDate);
},
child: Container(
color: AppColors.WHITE,
alignment: Alignment.center,
child: Container(
width: ScreenUtil.px2pt(60),
height: ScreenUtil.px2pt(60),
alignment: Alignment.center,
decoration: BoxDecoration(
color: AppColors.BLUE_TEXT,
borderRadius: BorderRadius.all(Radius.circular(100)),
),
child: Text(
value.day.toString(),
style: TextStyle(color: AppColors.WHITE),
),
),
),
);
} else {
if (value == widget.initDate) {
return GestureDetector(
onTap: () {
widget.onChange(widget.initDate);
},
child: Container(
color: AppColors.WHITE,
alignment: Alignment.center,
child: Text(
value.day.toString(),
style: TextStyle(color: AppColors.BLUE_TEXT),
)),
);
} else {
if (value.isAfter(widget.initDate)) {
/// 在今天之后的时间无法点击
return GestureDetector(
child: Container(
alignment: Alignment.center,
child: Text(
value.day.toString(),
style: TextStyle(color: AppColors.BLACK3),
)),
);
} else {
/// 在今天之前的时间可以点击
return GestureDetector(
onTap: () {
widget.onChange(value);
},
child: Container(
color: AppColors.WHITE,
alignment: Alignment.center,
child: Container(
child: Text(
value.day.toString(),
style: TextStyle(color: AppColors.BLACK1),
),
)),
);
}
}
}
}).toList();
return dayWidgets;
}
@override
Widget build(BuildContext context) {
List<Widget> list = dayItems();
return Container(
height: ScreenUtil.px2pt(600),
child: GridView.custom(
gridDelegate:
_DayPickerGridDelegate(mainAxisNumber: list.length > 35 ? 6 : 5),
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(0),
childrenDelegate:
SliverChildListDelegate(list, addRepaintBoundaries: false)),
);
}
}
/// 自定义GridView
class _DayPickerGridDelegate extends SliverGridDelegate {
final int mainAxisNumber;
const _DayPickerGridDelegate({
this.mainAxisNumber,
});
@override
SliverGridLayout getLayout(SliverConstraints constraints) {
const int columnCount = DateTime.daysPerWeek;
final double tileWidth = constraints.crossAxisExtent / columnCount;
final double tileHeight = ScreenUtil.px2pt(600) / mainAxisNumber;
return SliverGridRegularTileLayout(
crossAxisCount: columnCount,
mainAxisStride: tileHeight,
crossAxisStride: tileWidth,
childMainAxisExtent: tileHeight,
childCrossAxisExtent: tileWidth,
reverseCrossAxis: axisDirectionIsReversed(constraints.crossAxisDirection),
);
}
@override
bool shouldRelayout(_DayPickerGridDelegate oldDelegate) => false;
}
const _DayPickerGridDelegate _kDayPickerGridDelegate = _DayPickerGridDelegate();
import 'package:flutter/cupertino.dart';
import 'package:flutter_xiaoe/utils/ScreenUtil.dart';
import 'package:flutter_xiaoe/utils/NetUtil.dart';
import 'package:flutter_xiaoe/config/Api.dart';
import 'package:flutter_xiaoe/config/Colors.dart';
import 'package:flutter/material.dart';
import 'package:flutter_xiaoe/widgets/login/ImageInputWidget.dart';
import 'package:flutter_xiaoe/config/Constant.dart';
import 'package:flutter_xiaoe/config/ImageConfig.dart';
import 'package:flutter_xiaoe/widgets/common/ShadowContainer.dart';
import 'package:flutter_xiaoe/widgets/login/GradientButton.dart';
import 'package:flutter_xiaoe/widgets/common/Header.dart';
class TimeUtil {
static const List<int> _daysInMonth = <int>[
31,
-1,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31
];
/// 获取这个月的天数
static int getDaysInMonth(int year, int month) {
if (month == DateTime.february) {
final bool isLeapYear =
(year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
if (isLeapYear) return 29;
return 28;
}
return _daysInMonth[month-1];
}
/// 获取周Header
static List<Widget> getDayHeaders(MaterialLocalizations localizations) {
List<Widget> list = [];
for (int i = localizations.firstDayOfWeekIndex; true; i = (i + 1) % 7) {
final String weekday = localizations.narrowWeekdays[i];
list.add(Flexible(
child: Container(
height: ScreenUtil.px2pt(80),
child: Center(
child: Text(
weekday,
style: TextStyle(
color: AppColors.BLACK1,
fontSize: ScreenUtil.px2ptFont(34),
),
),
),
)));
if (i == (localizations.firstDayOfWeekIndex - 1) % 7) break;
}
return list;
}
/// 得到这个月的第一天是星期几(0 是 星期日 1 是 星期一...)
static int computeFirstDayOffset(
int year, int month, MaterialLocalizations localizations) {
// 0-based day of week, with 0 representing Monday.
final int weekdayFromMonday = DateTime(year, month).weekday - 1;
// 0-based day of week, with 0 representing Sunday.
final int firstDayOfWeekFromSunday = localizations.firstDayOfWeekIndex;
// firstDayOfWeekFromSunday recomputed to be Monday-based
final int firstDayOfWeekFromMonday = (firstDayOfWeekFromSunday - 1) % 7;
// Number of days between the first day of week appearing on the calendar,
// and the day corresponding to the 1-st of the month.
return (weekdayFromMonday - firstDayOfWeekFromMonday) % 7;
}
/// 获取天
static List getDay(int year, int month, MaterialLocalizations localizations) {
List labels = [];
final int daysInMonth = getDaysInMonth(year, month);
final int firstDayOffset =
computeFirstDayOffset(year, month, localizations);
for (int i = 0; true; i += 1) {
// 1-based day of month, e.g. 1-31 for January, and 1-29 for February on
// a leap year.
final int day = i - firstDayOffset + 1;
if (day > daysInMonth) break;
if (day < 1) {
labels.add(0);
} else {
labels.add(DateTime(year, month, day));
}
}
return labels;
}
}