// ignore_for_file: unnecessary_brace_in_string_interps import 'dart:async'; import 'dart:math'; import 'package:fast/constants.dart'; import 'package:fast/extension/layout.dart'; import 'package:fast/model/model.dart'; import 'package:fast/utils/global.dart'; import 'package:fast/utils/size_fit.dart'; import 'package:fast/utils/util.dart'; import 'package:fast/view/component/fast_btn.dart'; import 'package:fast/view/component/fast.dart'; import 'package:fast/view/component/toast.dart'; import 'package:flutter/material.dart'; import 'alert_widget.dart'; // ignore: must_be_immutable class Record extends Dialog { FastState fast; int begin; int end; int target; Record( {Key? key, required this.begin, required this.target, required this.end, required this.fast}) : super(key: key); @override Widget build(BuildContext context) { EdgeInsets safePadding = MediaQuery.of(context).padding; return Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/bg.png'), fit: BoxFit.cover)), alignment: Alignment.center, child: Stack( children: [ GestureDetector( onTap: () { fast.closeRecordConfirm(); Navigator.of(context).pop(); }, child: Container( padding: EdgeInsets.fromLTRB(12.px, 5.px, 12.px, 5.px), margin: EdgeInsets.only(left: 8.px, top: 54.px), child: Image.asset( 'assets/images/close.png', width: 20.px, height: 20.px, ), ), ), RecordTip( begin: begin, end: end, target: target, fast: fast, ), RecordDetail( top: safePadding.top, bottom: safePadding.bottom, begin: begin, end: end, target: target, fast: fast, ) ], ), ); } } // ignore: must_be_immutable class RecordTip extends StatefulWidget { FastState fast; int begin; int end; int target; RecordTip( {Key? key, required this.begin, required this.target, required this.end, required this.fast}) : super(key: key); @override State createState() => _RecordTipState(); } class _RecordTipState extends State with TickerProviderStateMixin { late AnimationController controller; late AnimationController controller2; late Animation animation; late Animation moveAnimation; bool isRightTime = false; bool isOverTime = false; bool isOver24 = false; String rightStr = ''; String overTimeStr = ''; @override void initState() { super.initState(); controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 300)); controller2 = AnimationController( vsync: this, duration: const Duration(milliseconds: 300)); animation = Tween(begin: 0.0, end: 1.0).animate(controller); moveAnimation = Tween(begin: 0.0, end: 250.0).animate(controller2); controller.addListener(() { setState(() {}); }); controller2.addListener(() { setState(() {}); }); if ((widget.end - widget.target).abs() < 60) { isRightTime = true; int seconds = widget.target - widget.begin; int hour = seconds ~/ 3600; int minute = seconds % 3600 ~/ 60; rightStr = '时长 ${hour}小时${minute}分钟'; } if (widget.end - widget.target > 60) { isOverTime = true; } if (widget.end - widget.begin > 3600 * 24) { isOver24 = true; } if (isOverTime) { DateTime time = DateTime.fromMillisecondsSinceEpoch(widget.target * 1000); String hour = time.hour.toString().padLeft(2, '0'); String minute = time.minute.toString().padLeft(2, '0'); int seconds = widget.end - widget.target; int hour2 = seconds ~/ 3600; int minute2 = seconds % 3600 ~/ 60; overTimeStr = '由于您未能在 ${hour}:${minute}断食结束后进行记\n录,目前已超时 ${hour2}小时 ${minute2}分钟'; } Timer(const Duration(milliseconds: 300), () { controller.forward(); }); Timer(const Duration(milliseconds: 2300), () { controller2.forward(); controller.reverse(); }); } @override void dispose() { controller.dispose(); controller2.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Container( width: double.infinity, height: double.infinity, alignment: Alignment.center, child: Container( margin: EdgeInsets.only(bottom: moveAnimation.value + 150.px), height: 200, alignment: Alignment.center, child: ScaleTransition( scale: animation, child: Opacity( opacity: animation.value, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ if (isRightTime) const Text( '断食结束咯 🎉', //'恭喜您\n完成了预计断食', textAlign: TextAlign.center, style: TextStyle( color: kThemeColor, fontSize: 36, fontWeight: FontWeight.bold), ), if (isOverTime) Text( isOver24 ? '断食超过24小时咯❗️' : '断食超时咯❗️', // isOver24 ? '您断食超24小时了1' : '您断食超时了2', style: const TextStyle( color: kThemeColor, fontSize: 36, fontWeight: FontWeight.bold), ), SizedBox( height: 24.px, ), if (isRightTime) Text( // rightStr, '欢迎如约而至的你!你果然是个守时靠谱的小伙伴❤️ \n接下来,你可按原计划结束断食,也可提前或延后结束\n找到适合自己的断食时长后,就去参与断食挑战吧~', style: TextStyle( color: Colors.white, fontSize: 12.px, height: 1.5), ), if (isOverTime) Text( // overTimeStr, isOver24 ? '等你等得好辛苦,下次别再迟到啦😂\n准时记录,将有助于你参与挑战时也能准时打卡哦' : '等你等得好辛苦,下次别再迟到啦😂\n准时记录,将有助于你参与断食挑战时也能准时打卡哦', textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 12.px, height: 1.5), ), ], ), ), ), ), ); } } // ignore: must_be_immutable class RecordDetail extends StatefulWidget { FastState fast; double top; double bottom; int begin; int end; int target; RecordDetail( {Key? key, required this.top, required this.bottom, required this.begin, required this.end, required this.target, required this.fast}) : super(key: key); @override State createState() => _RecordDetailState(); } class _RecordDetailState extends State with SingleTickerProviderStateMixin { late AnimationController controller; late Animation alphaAnimation, topAnimation, bottomAnimation; bool isRightTime = false; bool isOverTime = false; bool isOver24 = false; bool isEarly = false; bool isExpandTime = false; int enterTime = 0; DateTime? endTime; int? expandSeconds; @override void initState() { enterTime = widget.end; controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 300)); alphaAnimation = Tween(begin: 0.0, end: 1.0).animate(controller); topAnimation = Tween(begin: 0.0, end: widget.top + 66.px).animate(controller); bottomAnimation = Tween(begin: 0.0, end: widget.bottom).animate(controller); controller.addListener(() { setState(() {}); }); if ((widget.end - widget.target).abs() < 60) { isRightTime = true; } if (widget.end - widget.target > 60) { isOverTime = true; } if (widget.end - widget.begin > 3600 * 24) { isOver24 = true; } if (widget.end - widget.target < -30) { isEarly = true; } Timer(Duration(milliseconds: isEarly ? 500 : 2500), () { controller.forward(); }); super.initState(); } @override void dispose() { controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Container( alignment: Alignment.center, child: Flex( direction: Axis.vertical, mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( height: topAnimation.value, ), Opacity( opacity: alphaAnimation.value, child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Image.asset( 'assets/images/newer.png', width: 298.px, height: 28.px, ), SizedBox( height: 6.px, ), Image.asset( 'assets/images/single_record.png', width: 179.px, height: 48.px, ), SizedBox( height: 40.px, ), RecordContent( detailState: this, ), ], ), ), const Expanded(child: SizedBox()), Opacity( opacity: alphaAnimation.value, child: Column( children: [ FastBtn( title: '确定', disable: false, width: 228.px, height: 48.px, callback: () { if (Global().allowNotification == false && Global().pushEnable) { Util().showNotificationStatus(context); return; } if (endTime != null) { if (isExpandTime) { widget.fast.expandTime(expandSeconds); } else { // Global().mainPage.showMe(); widget.fast.confirmRecord( endTime!.millisecondsSinceEpoch ~/ 1000, isRightTime, enterTime); } widget.fast.closeRecordConfirm(); Navigator.of(context).pop(); } }), SizedBox( height: 16.px, ), GestureDetector( onTap: () { abandon(); }, child: Container( width: 104.px, height: 48.px, alignment: Alignment.center, child: Text( '放弃记录', style: TextStyle( color: const Color(0x99C4CCDA), fontSize: 14.px), ), ), ) ], ), ), SizedBox( height: bottomAnimation.value, ), ], ), ); } void updateEndTime(DateTime dateTime) { endTime = dateTime; } void updateExpandSeconds(int secs) { expandSeconds = secs; } void updateStatus(bool isExpand) { setState(() { isExpandTime = isExpand; }); } void abandon() { showDialog( context: context, barrierDismissible: false, barrierColor: const Color(0xF2000D1F), builder: (BuildContext context) { return AlertWidget( title: '确定要放弃本次记录吗?', confirm: '确定', confirmCallback: () { widget.fast.closeRecordConfirm(); Navigator.of(context).pop(); giveupAndQuitPage(); }); }); } void giveupAndQuitPage() { widget.fast.closeRecordConfirm(); widget.fast.giveupRecord(); Navigator.of(context).pop(); } } // ignore: must_be_immutable class RecordContent extends StatefulWidget { _RecordDetailState detailState; RecordContent({Key? key, required this.detailState}) : super(key: key); @override State createState() => _RecordContentState(); } class _RecordContentState extends State with TickerProviderStateMixin { late AnimationController ctrl1, ctrl2, ctrl3; late Animation expand1, expand2, expand3; late String startTime; late String endTime; late String betweenTime; late DateTime tempDate; bool allowMinus1 = false; bool allowAdd1 = false; //超时按钮调整时间 int expandSeconds = 15 * 60; bool allowMinus2 = false; bool allowAdd2 = true; int selIndex = 0; @override void initState() { super.initState(); ctrl1 = AnimationController( vsync: this, duration: const Duration(milliseconds: 300)); expand1 = Tween(begin: 56.px, end: 153.px).animate(ctrl1); ctrl2 = AnimationController( vsync: this, duration: const Duration(milliseconds: 300)); expand2 = Tween(begin: 56.px, end: 191.px).animate(ctrl2); ctrl3 = AnimationController( vsync: this, duration: const Duration(milliseconds: 300)); expand3 = Tween(begin: 56.px, end: 161.px).animate(ctrl3); DateTime dtBegin = DateTime.fromMillisecondsSinceEpoch( widget.detailState.widget.begin * 1000); DateTime dtEnd; if (widget.detailState.widget.end - widget.detailState.widget.begin > 23 * 3600) { dtEnd = DateTime.fromMillisecondsSinceEpoch( widget.detailState.widget.begin * 1000 + 23 * 3600 * 1000); } else { dtEnd = DateTime.fromMillisecondsSinceEpoch( widget.detailState.widget.end * 1000); } DateTime dtTarget = DateTime.fromMillisecondsSinceEpoch( widget.detailState.widget.target * 1000); int minEnd = min(dtTarget.millisecondsSinceEpoch, dtEnd.millisecondsSinceEpoch); DateTime minEndDate = DateTime.fromMillisecondsSinceEpoch(minEnd); tempDate = dtEnd; startTime = '${dtBegin.hour.toString().padLeft(2, '0')}:${dtBegin.minute.toString().padLeft(2, '0')}'; if (widget.detailState.isRightTime) { endTime = '${dtTarget.hour.toString().padLeft(2, '0')}:${dtTarget.minute.toString().padLeft(2, '0')}'; int seconds = widget.detailState.widget.target - widget.detailState.widget.begin; betweenTime = '断食${seconds ~/ 3600}小时${(seconds % 3600) ~/ 60}分钟'; tempDate = dtTarget; } else /*if (widget.detailState.isOverTime)*/ { endTime = '${dtEnd.hour.toString().padLeft(2, '0')}:${dtEnd.minute.toString().padLeft(2, '0')}'; int seconds = widget.detailState.widget.end - widget.detailState.widget.begin; if (seconds > 23 * 3600) { seconds = 23 * 3600; } betweenTime = '断食${seconds ~/ 3600}小时${(seconds % 3600) ~/ 60}分钟'; } if (serverTime().day == dtBegin.day) { startTime = '今天 ' + startTime; } else if (DateTime.fromMillisecondsSinceEpoch( serverTime().millisecondsSinceEpoch - 23 * 3600 * 1000) .day == dtBegin.day) { startTime = '昨天 ' + startTime; } else { startTime = dtBegin.month.toString() + '.' + dtBegin.day.toString() + ' ' + startTime; } if (serverTime().day == dtEnd.day) { endTime = '今天 ' + endTime; } else if (DateTime.fromMillisecondsSinceEpoch( serverTime().millisecondsSinceEpoch - 23 * 3600 * 1000) .day == dtEnd.day) { endTime = '昨天 ' + endTime; } else { endTime = dtEnd.month.toString() + '.' + dtEnd.day.toString() + ' ' + endTime; } ctrl1.addListener(() { setState(() {}); }); ctrl2.addListener(() { setState(() {}); }); ctrl3.addListener(() { setState(() {}); }); ctrl1.forward(); tempDate = minEndDate; calulate(); } DateTime serverTime() { int milliseconds = DateTime.now().millisecondsSinceEpoch; milliseconds = milliseconds + Global().timeSeconds * 1000; return DateTime.fromMillisecondsSinceEpoch(milliseconds); } calulate() { endTime = '${tempDate.hour.toString().padLeft(2, '0')}:${tempDate.minute.toString().padLeft(2, '0')}'; // if (tempDate.day == DateTime.now().day) { // endTime = '今天' + endTime; // } else { // endTime = '昨天' + endTime; // } if (serverTime().day == tempDate.day) { endTime = '今天 ' + endTime; } else if (DateTime.fromMillisecondsSinceEpoch( serverTime().millisecondsSinceEpoch - 23 * 3600 * 1000) .day == tempDate.day) { endTime = '昨天 ' + endTime; } else { endTime = tempDate.month.toString() + '.' + tempDate.day.toString() + ' ' + endTime; } int seconds = tempDate.millisecondsSinceEpoch ~/ 1000 - widget.detailState.widget.begin; if (seconds > 23 * 3600) { seconds = 23 * 3600; } betweenTime = '断食${seconds ~/ 3600}小时${(seconds % 3600) ~/ 60}分钟'; allowAdd1 = false; allowMinus1 = false; if (seconds - 15 * 60 > 3600) { allowMinus1 = true; } if (widget.detailState.widget.end - tempDate.millisecondsSinceEpoch ~/ 1000 - 15 * 60 >= 0 && seconds < 23 * 3600) { allowAdd1 = true; } widget.detailState.updateEndTime(tempDate); widget.detailState.updateExpandSeconds(expandSeconds); allowMinus2 = expandSeconds <= 15 * 60 ? false : true; FastBean currentFast = Global().currentFast!; int count = currentFast.endTime! - currentFast.startTime! + expandSeconds + 15 * 60; if (count >= 24 * 3600 || seconds >= 23 * 3600) { allowAdd2 = false; } else { allowAdd2 = true; } } @override void dispose() { ctrl1.dispose(); ctrl2.dispose(); ctrl3.dispose(); super.dispose(); } @override Widget build(BuildContext context) { if (widget.detailState.isRightTime) { return Column( children: [rightEnd(), earlyEnd(), delayEnd()], ); } return otherEnd(); //otherEnd(); } rightEnd() { FastBean currentFast = Global().currentFast!; int seconds = currentFast.endTime! - currentFast.startTime!; int hours = seconds ~/ 3600; int minutes = seconds ~/ 3600 ~/ 60; DateTime beginDateTime = DateTime.fromMillisecondsSinceEpoch(currentFast.startTime! * 1000); DateTime endDateTime = DateTime.fromMillisecondsSinceEpoch(currentFast.endTime! * 1000); return GestureDetector( onTap: () { ctrl1.forward(); ctrl2.reverse(); ctrl3.reverse(); selIndex = 0; widget.detailState.updateStatus(false); }, child: Container( height: expand1.value, width: 296.px, decoration: BoxDecoration( color: const Color(0xFF142133), borderRadius: BorderRadius.all(Radius.circular(36.px)), border: Border.all( color: selIndex == 0 ? const Color(0x99AAFF00) : Colors.transparent, width: 2.px)), constraints: BoxConstraints(maxHeight: expand1.value), child: Stack(clipBehavior: Clip.antiAlias, children: [ ListView( padding: EdgeInsets.zero, physics: const NeverScrollableScrollPhysics(), children: [ Container( margin: EdgeInsets.only(left: 16.px, right: 16.px), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: selIndex == 0 ? const Color(0x1AC4CCDA) : Colors.transparent))), child: Row( children: [ Container( margin: EdgeInsets.only(bottom: 2.px), child: Image.asset( selIndex == 0 ? 'assets/images/checked.png' : 'assets/images/check.png', width: 24.px, height: 24.px, )), Expanded( child: Text('按计划结束断食', textAlign: TextAlign.center, style: TextStyle( color: selIndex == 0 ? const Color(0xFFC4CCDA) : const Color(0x99C4CCDA), fontSize: 16.px, fontWeight: selIndex == 0 ? FontWeight.bold : FontWeight.normal, height: 1.0))) ], ).height(56.px).margin(right: 24.px), ), Text( '持续${hours}小时${minutes}分钟', style: TextStyle( color: kThemeColor, fontSize: 28.px, fontWeight: FontWeight.w600, fontFamily: 'Exo2', height: 1.0), textAlign: TextAlign.center, ).marginTop(16.px), SizedBox(height: 12.px), Text( "${beginDateTime.hour.toString().padLeft(2, '0')}:${beginDateTime.minute.toString().padLeft(2, '0')}~${endDateTime.hour.toString().padLeft(2, '0')}:${endDateTime.minute.toString().padLeft(2, '0')}", style: TextStyle( color: const Color(0x99C4CCDA), fontSize: 14.px, fontFamily: 'Exo2', height: 1.0), textAlign: TextAlign.center, ) ]) ]), ), ); } earlyEnd() { return GestureDetector( onTap: () { ctrl2.forward(); ctrl1.reverse(); ctrl3.reverse(); selIndex = 1; widget.detailState.updateStatus(false); }, child: Container( margin: EdgeInsets.only(top: 10.px), height: expand2.value, width: 296.px, decoration: BoxDecoration( color: const Color(0xFF142133), borderRadius: BorderRadius.all(Radius.circular(36.px)), border: Border.all( color: selIndex == 1 ? const Color(0x99AAFF00) : Colors.transparent, width: 2.px)), constraints: BoxConstraints(maxHeight: expand2.value), child: Stack(clipBehavior: Clip.antiAlias, children: [ ListView( padding: EdgeInsets.zero, physics: const NeverScrollableScrollPhysics(), children: [ Container( margin: EdgeInsets.only(left: 16.px, right: 16.px), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: selIndex == 1 ? const Color(0x1AC4CCDA) : Colors.transparent))), child: Row( children: [ Container( margin: EdgeInsets.only(bottom: 2.px), child: Image.asset( selIndex == 1 ? 'assets/images/checked.png' : 'assets/images/check.png', width: 24.px, height: 24.px, )), Expanded( child: Text('已提前结束断食', textAlign: TextAlign.center, style: TextStyle( color: selIndex == 1 ? const Color(0xFFC4CCDA) : const Color(0x99C4CCDA), fontWeight: selIndex == 1 ? FontWeight.bold : FontWeight.normal, fontSize: 16.px, height: 1.0))) ], ).height(56.px).margin(right: 24.px), ), SizedBox( height: 16.px, ), Text( startTime, textAlign: TextAlign.center, style: TextStyle( color: const Color(0x99C4CCDA), fontSize: 16.px, fontFamily: 'Exo2', height: 1.0, fontWeight: FontWeight.w600), ), SizedBox( height: 4.px, ), // Text('~', // style: TextStyle( // color: const Color(0x99C4CCDA), // fontSize: 16.px, // fontFamily: 'Exo2', // height: 1.0, // fontWeight: FontWeight.w600)), Row( children: [ SizedBox( width: 8.px, ), GestureDetector( onTap: () { if (allowMinus1) { setState(() { tempDate = DateTime.fromMillisecondsSinceEpoch( tempDate.millisecondsSinceEpoch - 15 * 60 * 1000); calulate(); }); } }, child: Image.asset( allowMinus1 ? 'assets/images/minus.png' : 'assets/images/minus_disable.png', width: 36.px, height: 36.px, ), ), Expanded( child: Text( endTime, textAlign: TextAlign.center, style: TextStyle( color: kThemeColor, fontSize: 28.px, fontFamily: 'Exo2', fontWeight: FontWeight.w600), )), GestureDetector( onTap: () { if (allowAdd1) { setState(() { tempDate = DateTime.fromMillisecondsSinceEpoch( tempDate.millisecondsSinceEpoch + 15 * 60 * 1000); calulate(); }); } }, child: Image.asset( allowAdd1 ? 'assets/images/plus.png' : 'assets/images/plus_disable.png', width: 36.px, height: 36.px, ), ), SizedBox( width: 8.px, ), ], ), Text(betweenTime, textAlign: TextAlign.center, style: TextStyle( color: const Color(0x99C4CCDA), fontSize: 14.px)) ]) ]), ), ); } delayEnd() { FastBean currentFast = Global().currentFast!; // int seconds = currentFast.endTime! - currentFast.startTime!; // int hours = seconds ~/ 3600; // int minutes = seconds ~/ 3600 ~/ 60; // DateTime beginDateTime = // DateTime.fromMillisecondsSinceEpoch(currentFast.startTime! * 1000); DateTime endDateTime = DateTime.fromMillisecondsSinceEpoch( currentFast.endTime! * 1000 + expandSeconds * 1000); return GestureDetector( onTap: () { if (!allowAdd2 && !allowMinus1) { return; } ctrl3.forward(); ctrl2.reverse(); ctrl1.reverse(); selIndex = 2; widget.detailState.updateStatus(true); }, child: Opacity( opacity: !allowAdd2 && !allowMinus1 ? 0.7 : 1.0, child: Container( height: expand3.value, width: 296.px, margin: EdgeInsets.only(top: 10.px), decoration: BoxDecoration( color: const Color(0xFF142133), borderRadius: BorderRadius.all(Radius.circular(36.px)), border: Border.all( color: selIndex == 2 ? const Color(0x99AAFF00) : Colors.transparent, width: 2.px)), constraints: BoxConstraints(maxHeight: expand3.value), child: Stack(clipBehavior: Clip.antiAlias, children: [ ListView( padding: EdgeInsets.zero, physics: const NeverScrollableScrollPhysics(), children: [ Container( margin: EdgeInsets.only(left: 16.px, right: 16.px), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: selIndex == 2 ? const Color(0x1AC4CCDA) : Colors.transparent))), child: Row( children: [ Container( margin: EdgeInsets.only(bottom: 2.px), child: Image.asset( selIndex == 2 ? 'assets/images/checked.png' : 'assets/images/check.png', width: 24.px, height: 24.px, ), ), Expanded( child: Text('要延后结束断食', textAlign: TextAlign.center, style: TextStyle( color: selIndex == 2 ? const Color(0xFFC4CCDA) : const Color(0x99C4CCDA), fontSize: 16.px, fontWeight: selIndex == 2 ? FontWeight.bold : FontWeight.normal, height: 1.0))) ], ).height(56.px).margin(right: 24.px), ), Row( children: [ SizedBox( width: 8.px, ), GestureDetector( onTap: () { if (allowMinus2) { setState(() { expandSeconds = expandSeconds - 15 * 60; calulate(); }); } }, child: Image.asset( allowMinus2 ? 'assets/images/minus.png' : 'assets/images/minus_disable.png', width: 36.px, height: 36.px, ), ), Expanded( child: Text( '${expandSeconds ~/ 3600}小时${expandSeconds % 3600 ~/ 60}分钟', textAlign: TextAlign.center, style: TextStyle( color: kThemeColor, fontSize: 24.px, fontFamily: 'Exo2', fontWeight: FontWeight.w600), )), GestureDetector( onTap: () { if (allowAdd2) { setState(() { expandSeconds = expandSeconds + 15 * 60; calulate(); }); } }, child: Image.asset( allowAdd2 ? 'assets/images/plus.png' : 'assets/images/plus_disable.png', width: 36.px, height: 36.px, ), ), SizedBox( width: 8.px, ), ], ).marginTop(16.px), Text( "预计${endDateTime.hour.toString().padLeft(2, '0')}:${endDateTime.minute.toString().padLeft(2, '0')}结束断食", textAlign: TextAlign.center, style: TextStyle( color: const Color(0x99C4CCDA), fontSize: 14.px)) ]) ]), ), ), ); } otherEnd() { return Container( width: 296.px, height: 191.px, constraints: BoxConstraints(maxHeight: 191.px), padding: EdgeInsets.only(left: 16.px, right: 16.px), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(32.px)), color: const Color(0xFF142133)), child: Stack( clipBehavior: Clip.hardEdge, children: [ Column( children: [ Container( height: 54.px, alignment: Alignment.center, child: Text( '结束断食时间', style: TextStyle( color: const Color(0xFFC4CCDA), fontSize: 16.px), ), decoration: const BoxDecoration( border: Border( bottom: BorderSide(color: Color(0x1AC4CCDA))))), SizedBox( height: 16.px, ), Text( startTime, style: TextStyle( color: const Color(0x99C4CCDA), fontSize: 16.px, fontFamily: 'Exo2', height: 1.0, fontWeight: FontWeight.w600), ), SizedBox( height: 4.px, ), // Text('~', // style: TextStyle( // color: const Color(0x99C4CCDA), // fontSize: 16.px, // fontFamily: 'Exo2', // height: 1.0, // fontWeight: FontWeight.w600)), Row( children: [ SizedBox( width: 8.px, ), GestureDetector( onTap: () { if (allowMinus1) { setState(() { tempDate = DateTime.fromMillisecondsSinceEpoch( tempDate.millisecondsSinceEpoch - 15 * 60 * 1000); calulate(); }); } else { showDialog( context: context, barrierDismissible: false, barrierColor: Colors.transparent, builder: (BuildContext context) { return Toast( title: '记录断食时长\n不能短于1小时哦', showError: true, content: const SizedBox( width: 0, ), ); }); } }, child: Image.asset( allowMinus1 ? 'assets/images/minus.png' : 'assets/images/minus_disable.png', width: 36.px, height: 36.px, ), ), Expanded( child: Text( endTime, textAlign: TextAlign.center, style: TextStyle( color: kThemeColor, fontSize: 28.px, fontFamily: 'Exo2', fontWeight: FontWeight.w600), )), GestureDetector( onTap: () { if (allowAdd1) { setState(() { tempDate = DateTime.fromMillisecondsSinceEpoch( tempDate.millisecondsSinceEpoch + 15 * 60 * 1000); calulate(); }); } else { int seconds = tempDate.millisecondsSinceEpoch ~/ 1000 - widget.detailState.widget.begin; if (seconds >= 23 * 3600) { showDialog( context: context, barrierDismissible: false, barrierColor: Colors.transparent, builder: (BuildContext context) { return Toast( title: '记录断食时长\n不能超过23小时哦', showError: true, content: const SizedBox( width: 0, ), ); }); } } }, child: Image.asset( allowAdd1 ? 'assets/images/plus.png' : 'assets/images/plus_disable.png', width: 36.px, height: 36.px, )), SizedBox( width: 8.px, ), ], ), Text(betweenTime, style: TextStyle( color: const Color(0x99C4CCDA), fontSize: 14.px)) ], ) ], ), ); } }