level_page.dart 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. import 'dart:convert';
  2. import 'dart:math';
  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_easyrefresh/easy_refresh.dart';
  7. import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
  8. import 'package:provider/provider.dart';
  9. import 'package:sport/bean/achievement_info.dart';
  10. import 'package:sport/bean/rank_game_info.dart';
  11. import 'package:sport/bean/user.dart';
  12. import 'package:sport/provider/lib/provider_widget.dart';
  13. import 'package:sport/provider/lib/simple_model.dart';
  14. import 'package:sport/provider/user_model.dart';
  15. import 'package:sport/router/navigator_util.dart';
  16. import 'package:sport/router/routes.dart';
  17. import 'package:sport/services/api/inject_api.dart';
  18. import 'package:sport/widgets/appbar.dart';
  19. import 'package:sport/widgets/box.dart';
  20. import 'package:sport/widgets/error.dart';
  21. import 'package:sport/widgets/image.dart';
  22. import 'package:sport/widgets/loading.dart';
  23. import 'package:sport/widgets/misc.dart';
  24. import 'package:sport/widgets/space.dart';
  25. import 'achievement_page.dart';
  26. class LevelPage extends StatefulWidget {
  27. @override
  28. State<StatefulWidget> createState() => _PageState();
  29. }
  30. class _PageState extends State<LevelPage> with InjectLoginApi {
  31. SimpleModel _model;
  32. bool _max = false;
  33. ScrollController _controller;
  34. int _brightness = 0;
  35. @override
  36. void initState() {
  37. super.initState();
  38. _model = SimpleModel(
  39. (page) async => [(await loginApi.getAchievementInfo()).data]);
  40. // _controller = ScrollController()
  41. // ..addListener(() {
  42. //// print(
  43. //// "[_controller.position.pixels] -------------------------- ${_controller.position.pixels}");
  44. // print("[_brightness]--------------------------$_brightness");
  45. // if (_controller.position.pixels >= 70) {
  46. // if (_brightness == 0) {
  47. // setState(() {
  48. // _brightness = 1;
  49. // });
  50. // }
  51. // } else {
  52. // if (_brightness == 1) {
  53. // setState(() {
  54. // _brightness = 0;
  55. // });
  56. // }
  57. // }
  58. // });
  59. }
  60. @override
  61. Widget build(BuildContext context) {
  62. return Scaffold(
  63. backgroundColor: Color(0xff241D19),
  64. body: Stack(
  65. children: <Widget>[
  66. Positioned(
  67. top: -100,
  68. left: 0,
  69. child: Container(
  70. width: MediaQuery.of(context).size.width,
  71. height: 373.0,
  72. decoration: BoxDecoration(
  73. image: DecorationImage(
  74. image: AssetImage("lib/assets/img/mylevel_bg.png"),
  75. fit: BoxFit.contain)),
  76. )),
  77. ProviderWidget<SimpleModel>(
  78. model: _model,
  79. onModelReady: (model) => model.initData(),
  80. builder: (_, model, __) {
  81. AchievementInfoData _data =
  82. model.list.isNotEmpty ? model.list.first : null;
  83. return EasyRefresh.builder(
  84. controller: model.refreshController,
  85. enableControlFinishRefresh: true,
  86. enableControlFinishLoad: true,
  87. onRefresh: () => model.refresh(),
  88. header: buildClassicalHeader(),
  89. builder: (context, physics, header, footer) {
  90. return CustomScrollView(
  91. controller: _controller,
  92. physics: physics,
  93. slivers: <Widget>[
  94. buildSliverAppBar(
  95. context,
  96. "我的等级",
  97. backgroundColor: _brightness == 0
  98. ? Color(0x00000000)
  99. : Color(0xffffffff),
  100. brightness: _brightness == 0 ? 1 : 0,
  101. textStyle: _brightness == 0
  102. ? TextStyle(
  103. fontWeight: FontWeight.w600,
  104. fontSize: 18.0,
  105. color: Color(0xffffffff))
  106. : TextStyle(
  107. fontWeight: FontWeight.w600,
  108. fontSize: 18.0,
  109. color: Color(0xff333333)),
  110. whiteBackButton: _brightness == 0 ? true : false,
  111. canBack: _brightness == 0 ? false : true,
  112. ),
  113. // header,
  114. if (model.isBusy)
  115. SliverToBoxAdapter(
  116. child: RequestLoadingWidget(),
  117. ),
  118. if (model.isIdle && _data != null)
  119. SliverToBoxAdapter(
  120. child: BoxWidget(
  121. body: Column(
  122. children: <Widget>[
  123. Padding(
  124. padding: const EdgeInsets.only(bottom: 8.0),
  125. child: Row(
  126. mainAxisAlignment:
  127. MainAxisAlignment.spaceBetween,
  128. children: <Widget>[
  129. Row(
  130. children: <Widget>[
  131. Text(
  132. "积分:",
  133. style: Theme.of(context)
  134. .textTheme
  135. .subtitle1,
  136. ),
  137. Space(
  138. width: 5.0,
  139. ),
  140. Text(
  141. '${_data.exp}',
  142. style: TextStyle(
  143. fontSize: 14.0,
  144. color: Color(0xffFFC400)),
  145. )
  146. ],
  147. ),
  148. InkWell(
  149. child: Row(
  150. children: <Widget>[
  151. Padding(
  152. child: Text(
  153. "积分商城",
  154. style: Theme.of(context)
  155. .textTheme
  156. .bodyText1,
  157. ),
  158. padding: EdgeInsets.only(right: 5.0),
  159. ),
  160. arrowRight4()
  161. ],
  162. ),
  163. onTap: () {
  164. NavigatorUtil.go(
  165. context, Routes.scoreShopPage);
  166. },
  167. )
  168. ],
  169. ),
  170. ),
  171. Padding(
  172. padding: const EdgeInsets.only(
  173. top: 16.0, bottom: 8.0),
  174. child: Container(
  175. child: CachedNetworkImage(
  176. width: 130.0,
  177. height: 130.0,
  178. imageUrl: _data.level.logo ?? "",fit: BoxFit.contain,))),
  179. Text(
  180. "Lv.${_data.level.level}",
  181. style: Theme.of(context).textTheme.headline3,
  182. ),
  183. Space(
  184. height: 24,
  185. ),
  186. Row(
  187. mainAxisAlignment: MainAxisAlignment.end,
  188. children: <Widget>[
  189. Row(
  190. children: <Widget>[
  191. Text(
  192. "${_data.exp}",
  193. style: TextStyle(
  194. fontSize: 11,
  195. color: Theme.of(context).accentColor),
  196. ),
  197. Text("/${_data.exp + _data.nextLevelExp}",
  198. style: TextStyle(fontSize: 11)),
  199. ],
  200. ),
  201. ],
  202. ),
  203. Space(
  204. height: 2,
  205. ),
  206. ClipRRect(
  207. borderRadius: BorderRadius.circular(10),
  208. child: Container(
  209. child: CustomPaint(
  210. painter: _ProgressBar(
  211. _data.exp /
  212. (_data.nextLevelExp + _data.exp),
  213. ),
  214. child: Container(
  215. height: 12,
  216. ),
  217. ),
  218. // height: 12,
  219. ),
  220. ),
  221. Space(
  222. height: 8,
  223. ),
  224. Row(
  225. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  226. children: <Widget>[
  227. Row(
  228. children: <Widget>[
  229. Text("经验值:",
  230. style: Theme.of(context)
  231. .textTheme
  232. .subtitle1),
  233. Space(
  234. width: 2.0,
  235. ),
  236. Text(
  237. "${_data.exp}",
  238. style: Theme.of(context)
  239. .textTheme
  240. .subtitle1
  241. .copyWith(
  242. color: Theme.of(context)
  243. .accentColor),
  244. ),
  245. ],
  246. ),
  247. Text(
  248. "再获得 ${_data.nextLevelExp} 经验可升到下一段",
  249. style: Theme.of(context).textTheme.bodyText1,
  250. ),
  251. ],
  252. ),
  253. Space(height: 10.0,),
  254. ],
  255. ))),
  256. if (model.isIdle && _data != null)
  257. SliverToBoxAdapter(
  258. child: BoxWidget(
  259. body: Column(
  260. children: <Widget>[
  261. Row(
  262. mainAxisAlignment:
  263. MainAxisAlignment.spaceBetween,
  264. children: <Widget>[
  265. Text(
  266. "我的成就",
  267. style:
  268. Theme.of(context).textTheme.headline3,
  269. ),
  270. if (_data.getAchievementList.length > -1 ||
  271. _max)
  272. InkWell(
  273. onTap: () {
  274. // setState(() {
  275. // _max = true;
  276. // });
  277. // NavigatorUtil.go(context, "achievement");
  278. NavigatorUtil.go(context,
  279. "${Routes.achievement}?data=${Uri.encodeComponent(json.encode(_data))}");
  280. },
  281. child: Row(
  282. children: <Widget>[
  283. Text(
  284. "查看全部 ",
  285. style: Theme.of(context)
  286. .textTheme
  287. .bodyText1,
  288. ),
  289. arrowRight4()
  290. ],
  291. ),
  292. ),
  293. ],
  294. ),
  295. Space(height: 10.0,),
  296. if (_data.getAchievementList.length == 0)
  297. Padding(
  298. padding: const EdgeInsets.all(30.0),
  299. child: Column(
  300. children: <Widget>[
  301. Image.asset(
  302. "lib/assets/img/${RequestErrorWidget.ASSETS_NO_RANK}"),
  303. Padding(
  304. padding: const EdgeInsets.fromLTRB(
  305. 0, 12, 0, 12),
  306. child: Text(
  307. "还未获得任何成就",
  308. style: Theme.of(context)
  309. .textTheme
  310. .bodyText2,
  311. ),
  312. ),
  313. ],
  314. )),
  315. if (_data.getAchievementList.length > 0)
  316. Padding(
  317. padding:
  318. EdgeInsets.only(top: 16.0,bottom: 0.0),
  319. child: StaggeredGridView.countBuilder(
  320. padding: EdgeInsets.zero,
  321. shrinkWrap: true,
  322. physics: NeverScrollableScrollPhysics(),
  323. crossAxisCount: 4,
  324. itemCount: _max
  325. ? _data.getAchievementList.length
  326. : min(4,
  327. _data.getAchievementList.length),
  328. itemBuilder:
  329. (BuildContext context, int index) =>
  330. achievementWidget(
  331. context,
  332. _data.getAchievementList[index],
  333. isRadius: false,
  334. ),
  335. mainAxisSpacing: 12.0,
  336. crossAxisSpacing: 12.0,
  337. staggeredTileBuilder: (int index) =>
  338. StaggeredTile.fit(1),
  339. ),
  340. ),
  341. // Center(
  342. // child: Padding(
  343. // padding: const EdgeInsets.all(1.0),
  344. // child: Row(
  345. // children: <Widget>[
  346. // Expanded(
  347. // child: Divider(
  348. // endIndent: 20.0,
  349. // ),
  350. // ),
  351. // Text("未获得成就", style: Theme.of(context).textTheme.bodyText1),
  352. // Expanded(
  353. // child: Divider(
  354. // indent: 20.0,
  355. // ),
  356. // ),
  357. // ],
  358. // ),
  359. // ),
  360. // ),
  361. // getList(_data)
  362. ],
  363. ),
  364. ),
  365. ),
  366. ],
  367. );
  368. });
  369. },
  370. )
  371. ],
  372. ));
  373. }
  374. }
  375. class _ProgressBar extends CustomPainter {
  376. final Paint _paint = Paint()
  377. ..color = Color(0xffeeeeee)
  378. ..isAntiAlias = true;
  379. final Paint _indicatorPaint = Paint()
  380. ..color = Color(0xffFFC400)
  381. ..isAntiAlias = true;
  382. double _paddingBar = 2;
  383. double percent;
  384. _ProgressBar(this.percent);
  385. @override
  386. void paint(Canvas canvas, Size size) {
  387. double indicator = size.width * min(1.0, this.percent);
  388. canvas.save();
  389. var rect = Rect.fromLTRB(0, size.height - 13, size.width, size.height);
  390. canvas.clipRRect(
  391. RRect.fromRectAndRadius(rect, Radius.circular(size.height / 2)),
  392. doAntiAlias: true);
  393. canvas.drawRect(rect, _paint);
  394. Paint _valuePaint = Paint()
  395. ..shader = LinearGradient(
  396. begin: Alignment.centerLeft,
  397. end: Alignment.centerRight,
  398. colors: <Color>[Color(0xffFFE600), Color(0xffFF9100)],
  399. ).createShader(rect);
  400. canvas.drawRect(
  401. Rect.fromLTRB(
  402. 0, size.height - 13, size.width * this.percent, size.height),
  403. _valuePaint);
  404. canvas.restore();
  405. Path path = Path()
  406. ..moveTo(indicator, size.height - 13 - _paddingBar)
  407. ..lineTo(indicator - 5, 0)
  408. ..lineTo(indicator + 5, 0)
  409. ..close();
  410. canvas.drawPath(path, _indicatorPaint);
  411. }
  412. @override
  413. bool shouldRepaint(CustomPainter oldDelegate) {
  414. return false;
  415. }
  416. }