dialog_check_rich2.dart 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'package:assets_audio_player/assets_audio_player.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:get/get.dart';
  6. import 'package:trackoffical_app/generated/assets.dart';
  7. import 'package:trackoffical_app/logger.dart';
  8. import 'package:trackoffical_app/service/app.dart';
  9. import 'package:trackoffical_app/view/ingame/dialog/dialog_base.dart';
  10. import 'package:trackoffical_app/view/ingame/dialog/dialog_check_text.dart';
  11. import 'package:trackoffical_app/widget/app_net_image.dart';
  12. import '../../../model/cp_extra_info_choice_question.dart';
  13. import '../../../model/m_control_point.dart';
  14. import '../../../screen.dart';
  15. import '../../../styles/theme.dart';
  16. Future<void> showDialogCheckRich(
  17. MControlPoint point,
  18. Duration? offAfter,
  19. ) async {
  20. while(Get.isOverlaysOpen){
  21. Get.back();
  22. }
  23. Get.dialog(DialogCheckRichSeq(
  24. point,
  25. offAfter,
  26. ));
  27. }
  28. class DialogCheckRichSeq extends StatefulWidget{
  29. const DialogCheckRichSeq(
  30. this.point, this.offAfter, {super.key}
  31. );
  32. final MControlPoint point;
  33. final Duration? offAfter;
  34. @override
  35. State<StatefulWidget> createState() {
  36. return DialogCheckRichSeqState();
  37. }
  38. }
  39. class DialogCheckRichSeqState extends State<DialogCheckRichSeq>{
  40. var seq = 0;
  41. var beanCount=0;
  42. @override
  43. void initState() {
  44. super.initState();
  45. }
  46. @override
  47. void dispose() {
  48. super.dispose();
  49. }
  50. @override
  51. Widget build(BuildContext context) {
  52. final isShowOriginality = App.to.userProfile.gameSettingsShowOriginality.value;
  53. if(seq==0){
  54. return DialogCheckText(
  55. text: '打点成功',
  56. color: const Color(0xffff870d),
  57. beanCount: 1,
  58. autoPlayAfter: 1.seconds,
  59. closeAfterPlay: !isShowOriginality,
  60. onStop: (){
  61. if(mounted){
  62. if (widget.point.extraInfo != null && isShowOriginality) {
  63. setState(() {
  64. seq = 1;
  65. });
  66. }
  67. }
  68. },
  69. );
  70. }
  71. if(seq==1){
  72. return DialogCheckRich(
  73. point: widget.point,
  74. offAfter: widget.offAfter,
  75. onBeanCount: (c) {
  76. beanCount = c;
  77. },
  78. onStop: (){
  79. if(mounted){
  80. setState(() {
  81. seq = 2;
  82. });
  83. }
  84. },
  85. );
  86. }
  87. if(seq==2){
  88. return DialogCheckText(
  89. text: '',
  90. color: const Color(0xffff870d),
  91. beanCount: beanCount,
  92. autoPlayAfter: 1.seconds,
  93. );
  94. }
  95. throw UnimplementedError();
  96. }
  97. }
  98. class DialogCheckRich extends DialogBaseOffCount {
  99. const DialogCheckRich({
  100. super.key,
  101. required this.point,
  102. required super.offAfter,
  103. required this.onBeanCount,
  104. required this.onStop
  105. }) : super(child: const SizedBox());
  106. final Function(int c) onBeanCount;
  107. final MControlPoint point;
  108. final VoidCallback onStop;
  109. @override
  110. State<StatefulWidget> createState() {
  111. return DialogCheckRichState();
  112. }
  113. }
  114. class DialogCheckRichState extends DialogBaseOffCountState<DialogCheckRich> {
  115. int? selectedIndex;
  116. var isFinish = false;
  117. final _audioPlayer = AssetsAudioPlayer.newPlayer();
  118. var isAnswerOk = false;
  119. @override
  120. void onStop() {
  121. widget.onStop();
  122. }
  123. void _setFinish() {
  124. setState(() {
  125. isFinish = true;
  126. });
  127. final src = isAnswerOk ? Assets.soundAnswerOk : Assets.soundAnswerFail;
  128. _audioPlayer.open(
  129. Audio(src),
  130. autoStart: true,
  131. showNotification: false,
  132. );
  133. 1.seconds.delay().then((value) {
  134. if (isActive && Get.isOverlaysOpen) {
  135. // Get.back();
  136. widget.onStop();
  137. }
  138. });
  139. }
  140. @override
  141. void dispose() {
  142. _audioPlayer.dispose();
  143. super.dispose();
  144. }
  145. @override
  146. Widget build(BuildContext context) {
  147. final style = (context.textTheme.titleLarge ?? const TextStyle())
  148. .copyWith(color: const Color(0xff333333), fontSize: 41.98.rpx);
  149. return DefaultTextStyle(
  150. style: style,
  151. child: Container(
  152. width: context.width,
  153. height: context.height,
  154. color: const Color(0xB8000000),
  155. alignment: Alignment.center,
  156. child: Center(
  157. child: Column(
  158. mainAxisSize: MainAxisSize.min,
  159. children: [
  160. Container(
  161. decoration: BoxDecoration(
  162. color: const Color(0xE6FFFCF4),
  163. borderRadius: BorderRadius.only(
  164. bottomLeft: Radius.circular(2.25.wp),
  165. bottomRight: Radius.circular(2.25.wp))),
  166. padding: EdgeInsets.fromLTRB(
  167. 4.5.wp,
  168. MediaQuery.of(context).padding.top + 4.5.wp,
  169. 4.5.wp,
  170. 11.4.wp),
  171. child: _wRich(),
  172. ),
  173. Obx(() => offCount(secondCount.value)),
  174. const Spacer()
  175. ],
  176. ),
  177. ),
  178. ));
  179. }
  180. Widget _wTitle(CPExtraInfoChoiceQuestion extraInfo) {
  181. const color = Color(0x80000000);
  182. return Row(
  183. crossAxisAlignment: CrossAxisAlignment.end,
  184. children: [
  185. Image.asset(Assets.imagesWarnFastThinker, width: 9.67.wp, color: color),
  186. Text(
  187. '快速思考',
  188. style: TextStyle(color: color, fontSize: 4.58.wp),
  189. ),
  190. Text(
  191. ' Think Fast',
  192. style: TextStyle(color: const Color(0x33333333), fontSize: 3.56.wp),
  193. ),
  194. const Spacer(),
  195. bean(extraInfo.beanCount, 3.31.wp)
  196. ],
  197. );
  198. }
  199. Widget _wRich() {
  200. final extraInfo = widget.point.extraInfo!;
  201. if (extraInfo is CPExtraInfoChoiceQuestion) {
  202. return wExtraInfoChoiceQuestion(extraInfo);
  203. } else {
  204. throw UnimplementedError('wExtraInfo: $extraInfo 未实现');
  205. }
  206. }
  207. Widget wExtraInfoChoiceQuestion(CPExtraInfoChoiceQuestion extraInfo) {
  208. final children = <Widget>[];
  209. var hasImage = false;
  210. if (extraInfo.image != null) {
  211. if (extraInfo.image!.md5.isNotEmpty) {
  212. hasImage = true;
  213. children.add(Container(
  214. decoration: BoxDecoration(
  215. border: Border.all(color: Colors.white, width: 0.78.wp),
  216. borderRadius: BorderRadius.circular(1.78.wp)),
  217. clipBehavior: Clip.hardEdge,
  218. height: 40.97.wp,
  219. child: ClipRRect(
  220. borderRadius: BorderRadius.circular(1.78.wp),
  221. child: AppNetImage(
  222. netImage: extraInfo.image!,
  223. fit: BoxFit.fitHeight,
  224. ))));
  225. }
  226. }
  227. children.addAll([
  228. SizedBox(height: 2.29.wp),
  229. ConstrainedBox(
  230. constraints: hasImage
  231. ? const BoxConstraints()
  232. : BoxConstraints(minHeight: 26.0.wp),
  233. child: Container(
  234. width: double.infinity,
  235. alignment: Alignment.centerLeft,
  236. child: Text(extraInfo.question, style: TextStyle(fontSize: 4.58.wp)),
  237. ),
  238. ),
  239. SizedBox(height: 2.29.wp),
  240. ]);
  241. var ascii = 65;
  242. for (var i = 0; i < extraInfo.answers.length; i++) {
  243. final one = extraInfo.answers[i];
  244. final sn = const Utf8Codec().decode([ascii]);
  245. final selected = i == selectedIndex;
  246. children.add(GestureDetector(
  247. onTap: () async {
  248. if (selectedIndex == null) {
  249. setState(() {
  250. selectedIndex = i;
  251. });
  252. if (i == extraInfo.rightIndex) {
  253. widget.onBeanCount(extraInfo.beanCount);
  254. }
  255. widget.point.userAnswerIndex = selectedIndex;
  256. widget.point.isAnswerCorrect =
  257. selectedIndex == extraInfo.rightIndex;
  258. isAnswerOk = widget.point.isAnswerCorrect;
  259. _setFinish();
  260. }
  261. },
  262. child: Container(
  263. margin: EdgeInsets.only(top: 2.8.wp, bottom: 2.8.wp),
  264. padding: EdgeInsets.only(left: 4.8.wp),
  265. alignment: Alignment.centerLeft,
  266. decoration: BoxDecoration(
  267. color: Color(selected ? 0xff00a0ff : 0xff017dc7),
  268. borderRadius: BorderRadius.circular(1.78.wp)),
  269. height: 13.49.wp,
  270. width: double.infinity,
  271. child: Text('$sn. $one',
  272. maxLines: 1,
  273. overflow: TextOverflow.ellipsis,
  274. style: const TextStyle(color: Colors.white)))));
  275. ascii++;
  276. }
  277. return Column(
  278. mainAxisSize: MainAxisSize.min,
  279. children: [
  280. _wTitle(extraInfo),
  281. const Divider(),
  282. Padding(
  283. padding: EdgeInsets.only(left: 8.52.wp, right: 8.52.wp, top: 7.26),
  284. child: Column(
  285. mainAxisSize: MainAxisSize.min,
  286. children: children,
  287. ))
  288. ],
  289. );
  290. }
  291. }
  292. class _Empty extends StatelessWidget {
  293. @override
  294. Widget build(BuildContext context) {
  295. SizeFit.screenInit(context);
  296. final info = CPExtraInfoChoiceQuestion()
  297. ..question = '计算题 23 + 8 - 6 = ?'
  298. ..answers = ['22', '2312312312311', '242323', '21231231211111231235']
  299. ..rightIndex = 3;
  300. return Scaffold(
  301. floatingActionButton: FloatingActionButton(
  302. onPressed: () => showDialogCheckRich(
  303. MControlPoint()
  304. ..sn = '3'
  305. ..areaId = 'A55'
  306. ..checkAfterPrev = 2.1.minutes
  307. ..extraInfo = info,
  308. 3.seconds,
  309. )),
  310. );
  311. }
  312. }
  313. void main() async {
  314. runApp(GetMaterialApp(theme: appThemeData(), home: _Empty()));
  315. }