import 'dart:convert'; import 'package:assets_audio_player/assets_audio_player.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:trackoffical_app/generated/assets.dart'; import 'package:trackoffical_app/model/m_control_point.dart'; import 'package:trackoffical_app/screen.dart'; import 'package:trackoffical_app/utils.dart'; import '../../../model/cp_extra_info.dart'; import '../../../model/cp_extra_info_choice_question.dart'; import '../../../styles/theme.dart'; import 'dialog_base.dart'; class DialogCheckRich extends StatefulWidget { const DialogCheckRich( {super.key, required this.point, required this.offAfter}); final Duration offAfter; final MControlPoint point; @override State createState() { return DialogCheckRichState(); } } class DialogCheckRichState extends State { Duration? offAfter; var isActive = true; final createAt = DateTime.now(); int? selectedIndex; var isFinish = false; var beanCount = 1; final _audioPlayer = AssetsAudioPlayer.newPlayer(); @override void initState() { super.initState(); workCount(); } @override void dispose() { isActive = false; _audioPlayer.dispose(); super.dispose(); } void _setFinish(){ setState(() { isFinish = true; }); _audioPlayer.open( Audio(Assets.soundAfterAnswer), autoStart: true, showNotification: false, ); 3.seconds.delay().then((value){ if(isActive && Get.isOverlaysOpen){ Get.back(); } }); } Future workCount() async { while (isActive) { if (isFinish) { return; } final offAfter = DateTime.now().difference(createAt); setState(() { this.offAfter = offAfter; }); if (offAfter > widget.offAfter) { _setFinish(); } await Future.delayed(100.milliseconds); } } @override Widget build(BuildContext context) { return isFinish ? wFinish() : DefaultTextStyle( style: context.textTheme.titleLarge ?? const TextStyle(), child: wMain()); } Widget wMain() { final extraInfo = widget.point.extraInfo; final mainHeight = extraInfo != null ? 261.45.rpx : 358.78.rpx; final point = widget.point; final style = context.textTheme.titleLarge ?? const TextStyle().copyWith( color: const Color(0xff333333), fontSize: 61.0.rpx, fontWeight: FontWeight.w700); var title = point.snString.isNotEmpty ? '${point.snString}点' : ''; if (point.areaId.isNotEmpty) { title += '(${point.areaId})'; } var imageSrc = 'assets/images/ic_cp.png'; if (point.isStart) { imageSrc = 'assets/images/ic_cp_start.png'; } if (point.isFinish) { imageSrc = 'assets/images/ic_cp_finish.png'; } final children = []; if (extraInfo != null) { children.add(wExtraInfo(extraInfo, mainHeight)); } children.add(Container( height: mainHeight, margin: EdgeInsets.only(left: 47.71.rpx, right: 47.71.rpx), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(17.18.rpx), boxShadow: [ BoxShadow( color: const Color(0x29000000), offset: Offset(5.73.rpx, 5.73.rpx), blurRadius: 11.45.rpx, spreadRadius: 11.45.rpx, ) ]), padding: EdgeInsets.only( left: 60.0.rpx, right: 60.0.rpx, top: 20.0.rpx, bottom: 20.0.rpx), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, children: [ RichText( text: TextSpan(text: '打点成功', style: style, children: [ TextSpan( text: ' +${widget.point.checkAfterPrev.toMinSecondString()}', style: style.copyWith(color: Colors.orange, fontSize: 30.53.rpx)) ])), Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( mainAxisSize: MainAxisSize.min, children: [ Image.asset(imageSrc, height: 37.18.rpx), SizedBox(width: 15.3.rpx), Text(title, style: style.copyWith(fontSize: 30.5.rpx)) ], ), bean(1, 30.53.rpx), ], ) ], ), )); int? second; if (offAfter != null) { second = ((widget.offAfter.inMilliseconds - offAfter!.inMilliseconds) / 1000) .ceil(); } return GestureDetector( // onTap: onBack, child: Container( width: context.width, height: context.height, color: const Color(0xB8000000), alignment: Alignment.center, child: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Stack( children: children, ), SizedBox(height: 50.0.rpx), Text( second?.toString() ?? '', style: context.textTheme.titleLarge?.copyWith( fontSize: 150.0.rpx, color: const Color(0xffff870d)), ) ], ), ), ), ); } Widget wFinish() { return GestureDetector( onTap: onBack, child: Container( width: context.width, height: context.height, color: const Color(0xB8000000), alignment: Alignment.center, child: Center( child: DefaultTextStyle( style: context.textTheme.titleLarge ?? const TextStyle().copyWith( color: const Color(0xffa0a0a0), fontSize: 45.8.rpx), child: Column(mainAxisSize: MainAxisSize.min, children: [ bean(beanCount, 74.43.rpx), SizedBox(height: 48.9.rpx), Text( '共获得$beanCount个百味豆', style: const TextStyle(color: Color(0xffa0a0a0)), ) ])))), ); } Future onBack() async { Get.back(); } Widget wExtraInfo(CPExtraInfo extraInfo, double mainHeight) { Widget child; if (extraInfo is CPExtraInfoChoiceQuestion) { child = wExtraInfoChoiceQuestion(extraInfo); } else { throw UnimplementedError('wExtraInfo: $extraInfo 未实现'); } return Container( margin: EdgeInsets.only(left: 64.8.rpx, right: 64.8.rpx), padding: EdgeInsets.only( left: 36.8.rpx, right: 36.8.rpx, top: mainHeight + 64.0.rpx, bottom: 40.0.rpx), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(17.18.rpx)), // child: child, child: DefaultTextStyle( style: context.textTheme.titleLarge ?? const TextStyle().copyWith( color: Colors.black, fontSize: 41.98.rpx, fontWeight: FontWeight.w700), child: child, ), ); } Widget wExtraInfoChoiceQuestion(CPExtraInfoChoiceQuestion extraInfo) { final answers = []; var ascii = 65; for (var i = 0; i < extraInfo.answers.length; i++) { final one = extraInfo.answers[i]; final sn = const Utf8Codec().decode([ascii]); final selected = i == selectedIndex; answers.add(GestureDetector( onTap: () async { if (selectedIndex == null) { setState(() { selectedIndex = i; }); if (i == extraInfo.rightIndex) { beanCount += extraInfo.beanCount; } widget.point.userAnswerIndex = selectedIndex; widget.point.isAnswerCorrect = selectedIndex == extraInfo.rightIndex; await 1.seconds.delay(); _setFinish(); } }, child: Container( padding: EdgeInsets.only(top: 15.0.rpx, bottom: 15.0.rpx), color: Colors.white, child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Image.asset( selected ? Assets.imagesIcRadioSelected : Assets.imagesIcRadio, height: 53.44.rpx, width: 53.44.rpx, ), SizedBox( width: 32.0.rpx, ), Expanded(child: Text( '$sn. $one', style: TextStyle( color: selected ? const Color(0xff00a0ff) : Colors.black), softWrap: true )) , ], )))); ascii++; } return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(extraInfo.question), SizedBox(height: 39.0.rpx), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: answers)), bean(extraInfo.beanCount, 30.53.rpx), ], ) ], ); } } class _Empty extends StatelessWidget { @override Widget build(BuildContext context) { SizeFit.screenInit(context); return const Scaffold( floatingActionButton: FloatingActionButton(onPressed: _showDialog), ); } } Future _showDialog() async { if (Get.isOverlaysOpen) { Get.back(); } final info = CPExtraInfoChoiceQuestion() ..question = '计算题 23 + 8 - 6 = ?' ..answers = ['22', '2312312312311', '242323', '21231231211111231235'] ..rightIndex = 3; Get.dialog( DialogCheckRich( point: MControlPoint() ..sn = '3' ..areaId = 'A55' ..checkAfterPrev = 2.1.minutes ..extraInfo = info, offAfter: 5.seconds, ), ); } void main() async { runApp(GetMaterialApp(theme: appThemeData(), home: _Empty())); }