achievement_detail_page.dart 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. import 'dart:math';
  2. import 'dart:ui';
  3. import 'package:cached_network_image/cached_network_image.dart';
  4. import 'package:flutter/cupertino.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter_swiper_plus/flutter_swiper_plus.dart';
  7. import 'package:sport/bean/user.dart';
  8. import 'package:sport/services/api/inject_api.dart';
  9. import 'package:sport/widgets/misc.dart';
  10. import 'package:sport/widgets/space.dart';
  11. class AchievementDetailPage extends StatefulWidget {
  12. final int id;
  13. final int userId;
  14. AchievementDetailPage(this.id, this.userId);
  15. @override
  16. State<StatefulWidget> createState() {
  17. return _PageState();
  18. }
  19. }
  20. class _PageState extends State<AchievementDetailPage> with InjectLoginApi {
  21. @override
  22. void initState() {
  23. super.initState();
  24. // _model = SimpleModel((page) async {
  25. // return List()..add((await loginApi.getAchieveDetailInfo(widget.id, userId: widget.userId == 0 ? null : "${widget.userId}")).data);
  26. // });
  27. }
  28. // @override
  29. // Widget build(BuildContext context) {
  30. // return Scaffold(
  31. //// backgroundColor: Color(0xffF1F1F1),
  32. // body: ProviderWidget<SimpleModel>(
  33. // model: _model,
  34. // onModelReady: (model) => model.initData(),
  35. // builder: (_, model, __) {
  36. // AchieveDetailInfoData _data = _model.list?.isNotEmpty == true ? _model.list.first : AchieveDetailInfoData();
  37. // return EasyRefresh.custom(
  38. // controller: model.refreshController,
  39. // enableControlFinishRefresh: true,
  40. // enableControlFinishLoad: true,
  41. // // onRefresh: () => model.refresh(),
  42. //// header: buildClassicalHeader(),
  43. //// footer: buildClassicalFooter(),
  44. // slivers: <Widget>[
  45. // buildSliverAppBar(context, "成就详情", backgroundColor: Theme.of(context).scaffoldBackgroundColor),
  46. // if (model.isBusy)
  47. // SliverToBoxAdapter(
  48. // child: RequestLoadingWidget(),
  49. // ),
  50. // if (model.isIdle)
  51. // SliverToBoxAdapter(
  52. // child: BoxWidget(
  53. // body: Column(
  54. // crossAxisAlignment: CrossAxisAlignment.center,
  55. // children: <Widget>[
  56. // Space(height: 10.0),
  57. // CachedNetworkImage(
  58. // width: 130.0,
  59. // height: 130.0,
  60. // imageUrl: _data.logo ?? "",
  61. // ),
  62. // Space(height: 12.0),
  63. // Text("${_data.name}", style: Theme.of(context).textTheme.headline3),
  64. // Space(height: 17.0),
  65. // Divider(),
  66. // Space(height: 12.0),
  67. // Row(
  68. // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  69. // children: <Widget>[
  70. // Text("成就名称:", style: Theme.of(context).textTheme.subtitle1!),
  71. // Text("${_data.name}", style: Theme.of(context).textTheme.bodyText2!.copyWith(color: Theme.of(context).accentColor))
  72. // ],
  73. // ),
  74. // Space(height: 8.0),
  75. // Row(
  76. // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  77. // children: <Widget>[
  78. // Text("成就条件:", style: Theme.of(context).textTheme.subtitle1!),
  79. // Text("${_data.conditionDetail}", style: Theme.of(context).textTheme.bodyText2!)
  80. // ],
  81. // ),
  82. // Space(height: 8.0),
  83. // Row(
  84. // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  85. // children: <Widget>[
  86. // Text("获取时间:", style: Theme.of(context).textTheme.subtitle1!),
  87. // Text("${_data.createdAt ?? '未获得成就'}", style: Theme.of(context).textTheme.bodyText2!)
  88. // ],
  89. // ),
  90. // Space(height: 8.0),
  91. // ],
  92. // ),
  93. // ),
  94. // ),
  95. // if (model.isIdle)
  96. // SliverToBoxAdapter(
  97. // child: BoxWidget(
  98. // body: Column(
  99. // crossAxisAlignment: CrossAxisAlignment.start,
  100. // children: <Widget>[
  101. // Row(
  102. // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  103. // children: <Widget>[
  104. // Text("晋级奖励:", style: Theme.of(context).textTheme.subtitle1!),
  105. // Text("经验值 +${_data.rewardExp} 积分+${_data.rewardScore}",
  106. // style: Theme.of(context).textTheme.bodyText2!.copyWith(color: Theme.of(context).accentColor))
  107. // ],
  108. // ),
  109. // Space(height: 4.0),
  110. // Divider(),
  111. // Space(height: 4.0),
  112. // Text("晋级进度: ", style: Theme.of(context).textTheme.subtitle1!),
  113. // Padding(
  114. // padding: EdgeInsets.symmetric(vertical: 10.0),
  115. // child: ClipRRect(
  116. // borderRadius: BorderRadius.circular(12),
  117. // child: Container(
  118. // child: CustomPaint(
  119. // painter: _ProgressBar(
  120. // ((_data?.nextConditionCount ?? 0) > 0) ? _data.conditionProgress / _data.nextConditionCount : 0,
  121. // ),
  122. // child: Container(
  123. // height: 8,
  124. // ),
  125. // ),
  126. // ),
  127. // ),
  128. // ),
  129. // Row(
  130. // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  131. // children: <Widget>[
  132. // Text('${_data.conditionProgress}${_data.conditionMeasure}', style: Theme.of(context).textTheme.bodyText1!.copyWith(fontSize: 11.0)),
  133. // Text('${_data.nextConditionCount}${_data.conditionMeasure}', style: Theme.of(context).textTheme.bodyText1!.copyWith(fontSize: 11.0))
  134. // ],
  135. // )
  136. // ],
  137. // ),
  138. // ),
  139. // ),
  140. // if (model.isIdle)
  141. // SliverToBoxAdapter(
  142. // child: Padding(
  143. // padding: const EdgeInsets.all(12.0),
  144. // child: Column(
  145. // children: <Widget>[
  146. // Row(
  147. // children: <Widget>[
  148. // Expanded(
  149. // child: Divider(
  150. // endIndent: 10.0,
  151. // ),
  152. // ),
  153. // Text("成就组"),
  154. // Expanded(
  155. // child: Divider(
  156. // indent: 10.0,
  157. // )),
  158. // ],
  159. // ),
  160. // ],
  161. // ),
  162. // )),
  163. // if (_data.relateAchievements?.length == 0)
  164. // Padding(padding: const EdgeInsets.all(24.0), child: Text("没有关联成就", style: Theme.of(context).textTheme.bodyText1!)),
  165. // if (model.isIdle && _data.relateAchievements.isNotEmpty)
  166. // SliverToBoxAdapter(
  167. // child: Text("${_data.relateAchievements}"),
  168. // ),
  169. //// SliverToBoxAdapter(
  170. //// child: StaggeredGridView.countBuilder(
  171. //// padding: EdgeInsets.symmetric(horizontal: 12.0),
  172. //// shrinkWrap: true,
  173. //// physics: NeverScrollableScrollPhysics(),
  174. //// crossAxisCount: 4,
  175. //// itemCount: _data.relateAchievements?.length,
  176. //// itemBuilder: (BuildContext context, int index) =>
  177. //// achievementWidget(context, _data.relateAchievements[index], replace: true, isRadius: false, jump: false),
  178. //// mainAxisSpacing: 12.0,
  179. //// crossAxisSpacing: 12.0,
  180. //// staggeredTileBuilder: (int index) => StaggeredTile.fit(1),
  181. //// ),
  182. //// )
  183. // ],
  184. // );
  185. // },
  186. // ));
  187. // }
  188. @override
  189. Widget build(BuildContext context) {
  190. // TODO: implement build
  191. // throw UnimplementedError();
  192. return Material(color: Colors.black.withOpacity(0.5), child: Column());
  193. }
  194. }
  195. class _ProgressBar extends CustomPainter {
  196. final Paint _paint = Paint()
  197. ..color = Color(0xfff1f1f1)
  198. ..isAntiAlias = true;
  199. final Paint _indicatorPaint = Paint()
  200. ..color = Color(0xffFFC400)
  201. ..isAntiAlias = true;
  202. double _paddingBar = 2;
  203. double percent;
  204. _ProgressBar(this.percent);
  205. @override
  206. void paint(Canvas canvas, Size size) {
  207. double indicator = size.width * min(1.0, this.percent);
  208. canvas.save();
  209. var rect = Rect.fromLTRB(0, size.height - 13, size.width, size.height);
  210. canvas.clipRRect(RRect.fromRectAndRadius(rect, Radius.circular(size.height / 2)), doAntiAlias: true);
  211. canvas.drawRect(rect, _paint);
  212. Paint _valuePaint = Paint()
  213. ..shader = LinearGradient(
  214. begin: Alignment.centerLeft,
  215. end: Alignment.centerRight,
  216. colors: <Color>[Color(0xffFFE600), Color(0xffFF9100)],
  217. ).createShader(rect);
  218. canvas.drawRect(Rect.fromLTRB(0, size.height - 13, size.width * this.percent, size.height), _valuePaint);
  219. canvas.restore();
  220. Path path = Path()
  221. ..moveTo(indicator, size.height - 13 - _paddingBar)
  222. ..lineTo(indicator - 5, 0)
  223. ..lineTo(indicator + 5, 0)
  224. ..close();
  225. canvas.drawPath(path, _indicatorPaint);
  226. }
  227. @override
  228. bool shouldRepaint(CustomPainter oldDelegate) {
  229. return false;
  230. }
  231. }
  232. Future<bool?> showSharePopup(BuildContext context, List<Achievement> relateAchievements, int id) {
  233. Iterable<Achievement> item = relateAchievements.where((element) => element.id == id);
  234. int startIndex = relateAchievements.indexOf(item.toList()[0]);
  235. ValueNotifier<int> _valueNotifierIndex = ValueNotifier(startIndex);
  236. int currentIndex = startIndex;
  237. return showGeneralDialog<bool>(
  238. context: context,
  239. barrierDismissible: true,
  240. barrierLabel: '',
  241. // barrierColor: Color(0xff241D19).withOpacity(0.8),
  242. transitionDuration: Duration(milliseconds: 200),
  243. // useRootNavigator: false,
  244. pageBuilder: (BuildContext context, Animation<double> animation, Animation<double>? secondaryAnimation) {
  245. return BackdropFilter(
  246. filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
  247. child: Material(
  248. color: Colors.transparent.withOpacity(0.8),
  249. child: Column(
  250. // mainAxisSize: MainAxisSize.max,
  251. children: <Widget>[
  252. Space(
  253. height: MediaQuery.of(context).padding.top + 31,
  254. ),
  255. Column(
  256. mainAxisSize: MainAxisSize.max,
  257. mainAxisAlignment: MainAxisAlignment.start,
  258. children: <Widget>[
  259. Container(
  260. padding: EdgeInsets.symmetric(horizontal: 17.0),
  261. alignment: Alignment.centerRight,
  262. child: InkWell(
  263. child: Container(
  264. width: 22.0,
  265. height: 22.0,
  266. decoration: BoxDecoration(image: DecorationImage(image: AssetImage("lib/assets/img/btn_close_white.png"))),
  267. ),
  268. onTap: () {
  269. Navigator.pop(context, false);
  270. },
  271. )),
  272. Space(
  273. height: 115,
  274. ),
  275. Stack(
  276. // fit: StackFit.expand,
  277. clipBehavior: Clip.none, alignment: Alignment.topCenter,
  278. children: <Widget>[
  279. Container(
  280. height: 278,
  281. child: new Swiper(
  282. // itemWidth: MediaQuery.of(context).size.width,
  283. loop: false,
  284. index: startIndex,
  285. itemBuilder: (BuildContext context, int index) {
  286. return Column(
  287. children: <Widget>[
  288. relateAchievements[index].createdAt != ""
  289. ? index != currentIndex
  290. ? Opacity(
  291. opacity: 0.5,
  292. child: Container(
  293. child: CachedNetworkImage(
  294. imageUrl: relateAchievements[index].logo ?? "",
  295. width: 180,
  296. height: 180,
  297. )))
  298. : Container(
  299. child: CachedNetworkImage(
  300. imageUrl: relateAchievements[index].logo ?? "",
  301. width: 180,
  302. height: 180,
  303. ))
  304. : index == currentIndex
  305. ? ColorFiltered(
  306. colorFilter: ColorFilter.matrix(<double>[
  307. 0.2126,
  308. 0.7152,
  309. 0.0722,
  310. 0,
  311. 0,
  312. 0.2126,
  313. 0.7152,
  314. 0.0722,
  315. 0,
  316. 0,
  317. 0.2126,
  318. 0.7152,
  319. 0.0722,
  320. 0,
  321. 0,
  322. 0,
  323. 0,
  324. 0,
  325. 1,
  326. 0,
  327. ]),
  328. child: CachedNetworkImage(
  329. // width: 70.0,
  330. // height: 70.0,
  331. imageUrl: relateAchievements[index].logo ?? ""),
  332. )
  333. : Opacity(
  334. opacity: 0.5,
  335. child: ColorFiltered(
  336. colorFilter: ColorFilter.matrix(<double>[
  337. 0.2126,
  338. 0.7152,
  339. 0.0722,
  340. 0,
  341. 0,
  342. 0.2126,
  343. 0.7152,
  344. 0.0722,
  345. 0,
  346. 0,
  347. 0.2126,
  348. 0.7152,
  349. 0.0722,
  350. 0,
  351. 0,
  352. 0,
  353. 0,
  354. 0,
  355. 1,
  356. 0,
  357. ]),
  358. child: CachedNetworkImage(
  359. // width: 70.0,
  360. // height: 70.0,
  361. imageUrl: relateAchievements[index].logo ?? ""),
  362. ),
  363. ),
  364. // if (index == currentIndex)
  365. // Column(
  366. // children: <Widget>[
  367. // Space(
  368. // height: 20.0,
  369. // ),
  370. // Space(
  371. // height: 5.0,
  372. // ),
  373. // ],
  374. // )
  375. ],
  376. );
  377. },
  378. viewportFraction: 0.5,
  379. scale: 0.3,
  380. itemCount: relateAchievements.length,
  381. pagination: new SwiperPagination(
  382. margin: new EdgeInsets.symmetric(vertical: 0.0),
  383. builder: DotSwiperPaginationBuilder(
  384. size: 6, activeSize: 6, color: Colors.white.withOpacity(0.5), activeColor: Theme.of(context).accentColor)),
  385. onIndexChanged: (index) {
  386. _valueNotifierIndex.value = index;
  387. currentIndex = index;
  388. },
  389. ),
  390. ),
  391. Positioned(
  392. // top: 120.0,
  393. top: 175,
  394. child: Container(
  395. child: ValueListenableBuilder(
  396. valueListenable: _valueNotifierIndex,
  397. builder: (BuildContext context, int value, Widget? child) {
  398. if (currentIndex == value) {
  399. return relateAchievements[value].createdAt != ""
  400. ? Column(
  401. mainAxisSize: MainAxisSize.min,
  402. children: <Widget>[
  403. Space(
  404. height: 25.0,
  405. ),
  406. Text(
  407. "${relateAchievements[value].name}",
  408. style: TextStyle(fontSize: 18.0, color: Colors.white, fontWeight: FontWeight.w600),
  409. ),
  410. Space(
  411. height: 10.0,
  412. ),
  413. Container(
  414. alignment: Alignment.center,
  415. child:
  416. Text("${relateAchievements[value].conditionDetail}", style: TextStyle(fontSize: 14.0, color: Colors.white)),
  417. ),
  418. Space(
  419. height: 60.0,
  420. ),
  421. Text("获取时间 ${relateAchievements[value].createdAt?.split(" ")[0]}"),
  422. Space(
  423. height: 16.0,
  424. ),
  425. // Container(
  426. // alignment: Alignment.center,
  427. // height: 37.5,
  428. // width: MediaQuery.of(context).size.width,
  429. // decoration: BoxDecoration(
  430. // image: DecorationImage(image: AssetImage("lib/assets/img/bg1_pop_achievement.png"), fit: BoxFit.cover)),
  431. // child: Text(
  432. // "晋级奖励 : 经验值 +${relateAchievements[value].rewardExp} 积分 +${relateAchievements[value].rewardScore}",
  433. // style: TextStyle(
  434. // fontSize: 14.0,
  435. // color: Theme.of(context).accentColor,
  436. // ),
  437. // strutStyle: fixedLine,
  438. // ),
  439. // ),
  440. ],
  441. )
  442. : Column(
  443. children: <Widget>[
  444. Space(
  445. height: 25.0,
  446. ),
  447. Text(
  448. "${relateAchievements[value].name}",
  449. style: TextStyle(fontSize: 18.0, color: Colors.white, fontWeight: FontWeight.w600),
  450. ),
  451. Space(
  452. height: 10.0,
  453. ),
  454. Text(
  455. "成就条件: ${relateAchievements[value].conditionDetail}",
  456. style: TextStyle(fontSize: 14.0, color: Colors.white),
  457. ),
  458. Space(
  459. height: 60.0,
  460. ),
  461. Text("未获得"),
  462. Space(
  463. height: 12.0,
  464. ),
  465. // Text(
  466. // "晋级奖励 : 经验值 +${relateAchievements[value].rewardExp} 积分 +${relateAchievements[value].rewardScore}",
  467. // style: TextStyle(fontSize: 14.0, color: Color(0xff999999)),
  468. // ),
  469. // Space(
  470. // height: 8.0,
  471. // ),
  472. Padding(
  473. padding: EdgeInsets.symmetric(vertical: 10.0),
  474. child: ClipRRect(
  475. borderRadius: BorderRadius.circular(12),
  476. child: Container(
  477. width: 183.0,
  478. child: CustomPaint(
  479. painter: _ProgressBar(
  480. (relateAchievements[value].conditionProgress > 0)
  481. ? relateAchievements[value].conditionProgress / relateAchievements[value].conditionCount
  482. : 0,
  483. ),
  484. child: Container(
  485. height: 8,
  486. ),
  487. ),
  488. ),
  489. ),
  490. ),
  491. // Space(
  492. // height: 5.0,
  493. // ),
  494. Text("${relateAchievements[value].conditionProgress} / ${relateAchievements[value].conditionCount}")
  495. ],
  496. );
  497. } else {
  498. return Container();
  499. }
  500. }),
  501. ),
  502. ),
  503. ],
  504. )
  505. ],
  506. ),
  507. ],
  508. ),
  509. ),
  510. );
  511. });
  512. }