challenge_result.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. import 'dart:async';
  2. import 'package:fast/constants.dart';
  3. import 'package:fast/model/model.dart';
  4. import 'package:fast/utils/global.dart';
  5. import 'package:fast/utils/size_fit.dart';
  6. import 'package:fast/view/component/fast.dart';
  7. import 'package:fast/view/component/fast_btn.dart';
  8. import 'package:fast/view/component/share.dart';
  9. import 'package:fast/view/component/toast.dart';
  10. import 'package:flutter/material.dart';
  11. // ignore: must_be_immutable
  12. class ChallengeResult extends StatefulWidget {
  13. FastResultBean resultBean;
  14. ChallengeResult({Key? key, required this.resultBean}) : super(key: key);
  15. @override
  16. State<ChallengeResult> createState() => _ChallengeResultState();
  17. }
  18. class _ChallengeResultState extends State<ChallengeResult>
  19. with SingleTickerProviderStateMixin {
  20. late AnimationController controller;
  21. late Animation topAni, centerAni, bottomAni;
  22. @override
  23. void initState() {
  24. controller = AnimationController(
  25. vsync: this, duration: const Duration(milliseconds: 1000));
  26. topAni = Tween(begin: 0.0, end: 1.0).animate(
  27. CurvedAnimation(parent: controller, curve: const Interval(0.0, 0.3)));
  28. centerAni = Tween(begin: 0.0, end: 1.0).animate(
  29. CurvedAnimation(parent: controller, curve: const Interval(0.3, 0.6)));
  30. bottomAni = Tween(begin: 0.0, end: 1.0).animate(
  31. CurvedAnimation(parent: controller, curve: const Interval(0.6, 0.9)));
  32. controller.addListener(() {
  33. setState(() {});
  34. });
  35. Timer(const Duration(milliseconds: 300), () {
  36. controller.forward();
  37. });
  38. // controller.forward();
  39. super.initState();
  40. }
  41. @override
  42. void dispose() {
  43. controller.dispose();
  44. super.dispose();
  45. }
  46. share() {
  47. showDialog(
  48. context: context,
  49. barrierDismissible: false,
  50. barrierColor: const Color(0xF2000D1F),
  51. builder: (BuildContext context) {
  52. return Share(
  53. type: 'challenge',
  54. resultBean: widget.resultBean,
  55. );
  56. });
  57. }
  58. @override
  59. Widget build(BuildContext context) {
  60. String resultTip = 'assets/images/challenge_failed.png';
  61. if (widget.resultBean.fastingStatus == 'END') {
  62. resultTip = 'assets/images/challenge_success.png';
  63. } else if (widget.resultBean.fastingStatus == 'TIMEOUT') {
  64. resultTip = 'assets/images/challenge_done.png';
  65. }
  66. var size = MediaQuery.of(context).size;
  67. double topSpace = 97.px;
  68. if (size.height<670){
  69. topSpace = 70.px;
  70. }
  71. return Container(
  72. decoration: BoxDecoration(
  73. image: DecorationImage(
  74. image: AssetImage(
  75. 'assets/images/${widget.resultBean.days}day_result_bg.png'),
  76. fit: BoxFit.cover),
  77. ),
  78. alignment: Alignment.center,
  79. child: Column(
  80. children: [
  81. SizedBox(
  82. height: topAni.value * topSpace,
  83. ),
  84. Opacity(
  85. opacity: topAni.value,
  86. child: Image.asset(
  87. resultTip,
  88. width: 204.px,
  89. height: 72.px,
  90. ),
  91. ),
  92. SizedBox(
  93. height: centerAni.value * 16.px,
  94. ),
  95. Opacity(
  96. opacity: centerAni.value,
  97. child: Container(
  98. width: 324.px,
  99. height: 260.px,
  100. decoration: BoxDecoration(
  101. color: const Color(0xCC000D1F),
  102. borderRadius: BorderRadius.all(Radius.circular(32.px)),
  103. border: Border.all(color: kThemeColor, width: 1.px),
  104. image: const DecorationImage(
  105. image: AssetImage('assets/images/statistic.png'),
  106. alignment: Alignment.topRight,
  107. scale: 2.9)),
  108. child: Statistic(resultBean: widget.resultBean,rate: 1.0,)),
  109. ),
  110. // SizedBox(
  111. // height: (1 - bottomAni.value) * 40.px + 20.px,
  112. // ),
  113. const Expanded(
  114. child: SizedBox(
  115. width: 0,
  116. height: 0,
  117. )),
  118. Opacity(
  119. opacity: bottomAni.value,
  120. child: Column(
  121. children: [
  122. Text(
  123. '邀请好友注册成功',
  124. style: TextStyle(
  125. decoration: TextDecoration.none,
  126. fontWeight: FontWeight.normal,
  127. fontSize: 12.px,
  128. color: const Color(0x99FFFFFF)),
  129. ),
  130. SizedBox(
  131. height: 7.px,
  132. ),
  133. Row(
  134. mainAxisAlignment: MainAxisAlignment.center,
  135. children: [
  136. Text(
  137. '我和ta各得逆龄石',
  138. style: TextStyle(
  139. decoration: TextDecoration.none,
  140. fontWeight: FontWeight.normal,
  141. fontSize: 12.px,
  142. height: 1.0,
  143. color: const Color(0x99FFFFFF)),
  144. ),
  145. SizedBox(
  146. width: 2.px,
  147. ),
  148. Text(
  149. '+3',
  150. style: TextStyle(
  151. decoration: TextDecoration.none,
  152. fontWeight: FontWeight.w600,
  153. fontSize: 14.px,
  154. height: 1.0,
  155. fontFamily: 'Exo2',
  156. color: const Color(0x99FFFFFF)),
  157. ),
  158. SizedBox(
  159. width: 2.px,
  160. ),
  161. Image.asset(
  162. 'assets/images/stone.png',
  163. width: 14.px,
  164. height: 14.px,
  165. )
  166. ],
  167. ),
  168. GestureDetector(
  169. onTap: () {
  170. share();
  171. },
  172. child: Container(
  173. width: 228.px,
  174. height: 48.px,
  175. margin: EdgeInsets.only(top: 25.px, bottom: 12.px),
  176. decoration: BoxDecoration(
  177. borderRadius:
  178. BorderRadius.all(Radius.circular(24.px)),
  179. border: Border.all(color: kThemeColor, width: 1.px),
  180. image: const DecorationImage(
  181. image: AssetImage('assets/images/invite.png'),
  182. alignment: Alignment.center,
  183. scale: 1.8)),
  184. ),
  185. ),
  186. FastBtn(
  187. title: '完成',
  188. disable: false,
  189. width: 228.px,
  190. height: 48.px,
  191. callback: () {
  192. tapDone();
  193. }),
  194. SizedBox(
  195. // height: 50.px,
  196. height: bottomAni.value * (size.height<812.px?54.px:108.px),
  197. )
  198. ],
  199. ),
  200. )
  201. ],
  202. ));
  203. }
  204. tapDone() {
  205. Navigator.of(context).pop();
  206. Global().mainPage.showMe();
  207. /*
  208. if (widget.resultBean.checkinStatus == 'SUCCESS') {
  209. //正常打卡
  210. Global().mainPage.showMe();
  211. showDialog(
  212. context: context,
  213. barrierDismissible: false,
  214. barrierColor: Colors.transparent,
  215. builder: (BuildContext context) {
  216. return Toast(
  217. title: '准时打卡',
  218. content: Row(
  219. mainAxisAlignment: MainAxisAlignment.center,
  220. children: [
  221. Text(
  222. '+1',
  223. style: TextStyle(
  224. color: Colors.white,
  225. fontSize: 16.px,
  226. fontWeight: FontWeight.w800,
  227. fontFamily: 'Exo2',
  228. decoration: TextDecoration.none),
  229. ),
  230. SizedBox(
  231. width: 3.px,
  232. ),
  233. Image.asset(
  234. 'assets/images/stone.png',
  235. width: 24.px,
  236. height: 24.px,
  237. )
  238. ],
  239. ),
  240. );
  241. });
  242. } else if (widget.resultBean.checkinStatus == 'TIMEOUT') {
  243. Global().mainPage.showMe();
  244. showDialog(
  245. context: context,
  246. barrierDismissible: false,
  247. barrierColor: Colors.transparent,
  248. builder: (BuildContext context) {
  249. return Toast(
  250. title: '超时打卡',
  251. content: const SizedBox(
  252. width: 0,
  253. ),
  254. );
  255. });
  256. //超时打卡
  257. } else {}*/
  258. Global().homePage.getDatas();
  259. if (Global().fastKey!.currentContext != null) {
  260. FastState seekBar = Global().fastKey!.currentState as FastState;
  261. seekBar.reset();
  262. }
  263. }
  264. }
  265. // ignore: must_be_immutable
  266. class Statistic extends StatelessWidget {
  267. FastResultBean resultBean;
  268. double rate;
  269. Statistic({Key? key, required this.resultBean,required this.rate}) : super(key: key);
  270. @override
  271. Widget build(BuildContext context) {
  272. List<Widget> widgets = [title('期末获得')];
  273. for (int i = 0; i < resultBean.rjvEarningsMax; i++) {
  274. if (i < resultBean.rjvEarnings) {
  275. widgets.add(stone());
  276. } else {
  277. widgets.add(stoneEmpty());
  278. }
  279. }
  280. return Column(
  281. children: [
  282. SizedBox(
  283. height: 28.px*rate,
  284. ),
  285. Row(
  286. children: [
  287. title('期初投入'),
  288. stone(),
  289. stone(),
  290. stone(),
  291. if (resultBean.rjvExpenditure > 3) stone(),
  292. if (resultBean.rjvExpenditure > 4) stone(),
  293. if (resultBean.rjvExpenditure > 5) stone(),
  294. if (resultBean.rjvExpenditure > 6) stone(),
  295. ],
  296. ),
  297. SizedBox(
  298. height: 10.px*rate,
  299. ),
  300. Row(
  301. children: widgets,
  302. ),
  303. Container(
  304. height: 1.px*rate,
  305. color: const Color(0x1AFFFFFF),
  306. margin: EdgeInsets.only(
  307. left: 32.px*rate, right: 32.px*rate, top: 16.px*rate, bottom: 12.px*rate),
  308. ),
  309. Row(
  310. children: [
  311. title('净收益'),
  312. Text(
  313. '${resultBean.rjvProfit}',
  314. style: boldStyle(),
  315. ),
  316. SizedBox(
  317. width: 4.px*rate,
  318. ),
  319. Container(
  320. margin: EdgeInsets.only(top: 5.px*rate),
  321. child: Text(
  322. '颗逆龄石',
  323. style: TextStyle(
  324. decoration: TextDecoration.none,
  325. color: Colors.white,
  326. fontWeight: FontWeight.w500,
  327. fontSize: 14.px*rate,
  328. height: 1.2,
  329. ),
  330. ),
  331. ),
  332. ],
  333. ),
  334. SizedBox(
  335. height: 6.px*rate,
  336. ),
  337. Row(
  338. children: [
  339. title('净收益率'),
  340. Text(
  341. '${resultBean.rjvYieldRate}%',
  342. style: boldStyle(),
  343. )
  344. ],
  345. ),
  346. Container(
  347. height: 1.px,
  348. color: kThemeColor,
  349. margin: EdgeInsets.only(
  350. left: 32.px*rate, right: 32.px*rate, top: 21.px*rate, bottom: 21.px*rate),
  351. ),
  352. Row(
  353. children: [
  354. title('逆龄石余额'),
  355. stone(),
  356. Text(
  357. '×${resultBean.rjvBalance}',
  358. style: boldStyle(),
  359. )
  360. ],
  361. ),
  362. ],
  363. );
  364. }
  365. Widget title(str) {
  366. return Container(
  367. width: 80.px*rate,
  368. margin: EdgeInsets.only(left: 32.px*rate),
  369. child: Text(
  370. str,
  371. style: TextStyle(
  372. decoration: TextDecoration.none,
  373. color: const Color(0xCCC4CCDA),
  374. fontWeight: FontWeight.normal,
  375. fontSize: 14.px*rate,
  376. height: 1.0,
  377. ),
  378. ),
  379. );
  380. }
  381. Widget stone() {
  382. return Container(
  383. child: Image.asset(
  384. 'assets/images/stone.png',
  385. width: 24.px*rate,
  386. height: 24.px*rate,
  387. ),
  388. margin: EdgeInsets.only(right: 2.px*rate),
  389. );
  390. }
  391. Widget stoneEmpty() {
  392. return Container(
  393. child: Image.asset(
  394. 'assets/images/stone_failed.png',
  395. width: 24.px*rate,
  396. height: 24.px*rate,
  397. ),
  398. margin: EdgeInsets.only(right: 2.px*rate),
  399. );
  400. }
  401. TextStyle boldStyle() {
  402. return TextStyle(
  403. color: Colors.white,
  404. fontSize: 24.px*rate,
  405. fontFamily: 'Exo2',
  406. fontWeight: FontWeight.w600,
  407. height: 1.0,
  408. decoration: TextDecoration.none);
  409. }
  410. }