RankList.dart 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. import 'package:flutter/material.dart';
  2. import '../styles/colors.dart';
  3. import 'dart:ui';
  4. import '../styles/totast.dart';
  5. import '../model/PlayerInfo.dart';
  6. import '../net/HttpManager.dart';
  7. import '../net/Result.dart';
  8. import 'package:flutter_redux/flutter_redux.dart';
  9. import '../redux/AppState.dart';
  10. import '../model/CompetitionSeason.dart';
  11. import '../widget/Dialog.dart';
  12. import 'dart:math';
  13. class RankList extends StatefulWidget {
  14. RankList({Key key, this.raceId = 0, this.gameId}) : super(key: key);
  15. final int raceId; // 用来储存传递过来的值
  16. final int gameId;
  17. @override
  18. RankListState createState() => RankListState();
  19. }
  20. class RankListState extends State<RankList> {
  21. String raceName = '2019';
  22. List raceNameList = ['2019', '2018', '2017'];
  23. List<PlayerInfo> rankList = [];
  24. ScrollController _mcontroller;
  25. bool scrollFlag = true;
  26. int currentPage = 1;
  27. int raceId = 0;
  28. int gameId = 0;
  29. List<CompetitionSeason> seasonList = [];
  30. PlayerInfo myPlayInfo;
  31. Future<void> getUserRank() async {
  32. Result res = await HttpManager.get('playerInfo/seasonUserRank',
  33. data: {'seasonId': raceId, 'userId': StoreProvider.of<AppState>(context).state.userInfo.id, 'gameId': gameId});
  34. print('*******************************************');
  35. print(res.data);
  36. if (res.success && res.data != null) {
  37. setState(() {
  38. myPlayInfo = PlayerInfo.fromJson(res.data);
  39. });
  40. } else {
  41. setState(() {
  42. myPlayInfo = null;
  43. });
  44. }
  45. currentPage = 1;
  46. getListPage();
  47. }
  48. Future<void> getListPage() async {
  49. scrollFlag = false;
  50. Toast.show(context, '加载中', -1, 'loading');
  51. Result res = await HttpManager.get('playerInfo/seasonRankPage', data: {'seasonId': raceId, 'currentPage': currentPage, 'pageNumber': 20});
  52. Toast.hide();
  53. List<PlayerInfo> list = rankList;
  54. if (currentPage == 1) {
  55. list = [];
  56. }
  57. if (res.success) {
  58. print(res.data['pp']);
  59. for (var item in res.data['pp']) {
  60. PlayerInfo tip = PlayerInfo.fromJson(item);
  61. list.add(tip);
  62. }
  63. if (res.data['page']['currentPage'] < res.data['page']['totalPage']) {
  64. scrollFlag = true;
  65. }
  66. } else {}
  67. setState(() {
  68. rankList = list;
  69. });
  70. if (rankList.isEmpty) {
  71. showBackDialog();
  72. }
  73. }
  74. //没有赛季排行数据弹窗
  75. void showBackDialog() {
  76. MyDialog.showDialog(context, '该赛季暂未产生排行数据,尽情期待...');
  77. // showDialog<Null>(
  78. // context: context,
  79. // barrierDismissible: false,
  80. // builder: (BuildContext context) {
  81. // return AlertDialog(
  82. // content: Container(
  83. // height: 50,
  84. // child: Text(
  85. // '该赛季暂未产生排行数据,尽情期待...',
  86. // style: TextStyle(color: Colors.black),
  87. // ),
  88. // ),
  89. // actions: <Widget>[
  90. // FlatButton(
  91. // child: Text('确定'),
  92. // onPressed: () {
  93. // Navigator.of(context).pop();
  94. // },
  95. // ),
  96. // ],
  97. // );
  98. // },
  99. // ).then((val) {
  100. // Navigator.of(context).pop();
  101. // });
  102. }
  103. Future<void> getSeasonInfo() async {
  104. Result res = await HttpManager.get('competitionSeason/all');
  105. if (res.success) {
  106. List<CompetitionSeason> list = [];
  107. for (var item in res.data) {
  108. list.add(CompetitionSeason.fromJson(item));
  109. }
  110. setState(() {
  111. seasonList = list;
  112. });
  113. } else {}
  114. if (seasonList.length > 0) {
  115. raceId = seasonList[0].id;
  116. gameId = seasonList[0].gameId;
  117. getUserRank();
  118. }
  119. }
  120. @override
  121. void initState() {
  122. raceId = widget.raceId;
  123. super.initState();
  124. _mcontroller = ScrollController();
  125. _mcontroller.addListener(() {
  126. if (_mcontroller.position.pixels == _mcontroller.position.maxScrollExtent) {
  127. if (scrollFlag) {
  128. currentPage++;
  129. getListPage();
  130. }
  131. }
  132. });
  133. Future.delayed(Duration.zero, () {
  134. getSeasonInfo();
  135. });
  136. }
  137. @override
  138. void dispose() {
  139. super.dispose();
  140. _mcontroller.dispose();
  141. }
  142. @override
  143. Widget build(BuildContext context) {
  144. return WillPopScope(
  145. child: Scaffold(
  146. body: Container(
  147. color: BG_SUB_COLOR,
  148. child: RefreshIndicator(
  149. color: PRIMARY_COLOR,
  150. backgroundColor: Colors.white,
  151. onRefresh: () async {
  152. await Future.delayed(const Duration(seconds: 1));
  153. getUserRank();
  154. },
  155. child: CustomScrollView(
  156. controller: _mcontroller,
  157. physics: AlwaysScrollableScrollPhysics(),
  158. slivers: <Widget>[
  159. _sliverAppBar(),
  160. myPlayInfo == null
  161. ? SliverToBoxAdapter()
  162. : SliverPersistentHeader(
  163. pinned: true, //是否固定在顶部
  164. floating: true,
  165. delegate: _SliverAppBarDelegate(
  166. minHeight: 66, //收起的高度
  167. maxHeight: 66, //展开的最大高度
  168. child: RankItem(
  169. myPlayInfo,
  170. myPlayInfo.rank,
  171. height: 66,
  172. color: 0xFF23253C,
  173. border:false
  174. )),
  175. ),
  176. _sliverList()
  177. ],
  178. )),
  179. ),
  180. ),
  181. onWillPop: () {
  182. Toast.hide();
  183. Navigator.pop(context);
  184. return Future.value(false);
  185. });
  186. }
  187. Widget _sliverAppBar() {
  188. CompetitionSeason competitionSeason;
  189. for (var item in seasonList) {
  190. if (item.id == raceId) {
  191. competitionSeason = item;
  192. }
  193. }
  194. return SliverAppBar(
  195. title: Text('排行榜'),
  196. centerTitle: true,
  197. actions: <Widget>[
  198. PopupMenuButton(
  199. initialValue: raceId,
  200. child: Row(
  201. crossAxisAlignment: CrossAxisAlignment.center,
  202. mainAxisAlignment: MainAxisAlignment.center,
  203. children: <Widget>[
  204. Text(
  205. competitionSeason != null ? competitionSeason.season : '',
  206. style: TextStyle(color: Colors.white, fontSize: 13, fontWeight: FontWeight.w400),
  207. ),
  208. Image.asset(
  209. 'images/icon_zhankai_baise.png',
  210. width: 20,
  211. ),
  212. Container(
  213. width: 15,
  214. )
  215. ],
  216. ),
  217. onSelected: (value) {
  218. setState(() {
  219. raceId = value;
  220. });
  221. getUserRank();
  222. },
  223. itemBuilder: (BuildContext context) {
  224. return seasonList.map((choice) {
  225. return PopupMenuItem(child: Text(choice.season), value: choice.id);
  226. }).toList();
  227. }),
  228. ],
  229. pinned: true);
  230. }
  231. Widget _slievrToBoxAdapter() {
  232. return SliverToBoxAdapter(
  233. child: Container(
  234. margin: EdgeInsets.only(bottom: 10),
  235. height: 196,
  236. // color: PRIMARY_COLOR,
  237. decoration:
  238. BoxDecoration(gradient: LinearGradient(begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [PRIMARY_COLOR, Color(0xFFF4B011)])),
  239. child: Row(
  240. mainAxisAlignment: MainAxisAlignment.center,
  241. children: widgetList(),
  242. ),
  243. ),
  244. );
  245. }
  246. Widget _sliverList() {
  247. return SliverList(
  248. delegate: SliverChildBuilderDelegate(
  249. (BuildContext context, int index) {
  250. if (index != rankList.length) {
  251. return RankItem(rankList[index], index);
  252. } else {
  253. return Padding(
  254. padding: EdgeInsets.only(top: 10, bottom: 68),
  255. child: Text(
  256. '没有更多了',
  257. textAlign: TextAlign.center,
  258. style: TextStyle(color: Colors.white30),
  259. ),
  260. );
  261. }
  262. },
  263. childCount: rankList.length + 1,
  264. ),
  265. );
  266. }
  267. List<Widget> widgetList() {
  268. List<Widget> list = [];
  269. if (rankList.isNotEmpty) {
  270. list.add(Container(
  271. margin: EdgeInsets.only(top: 0, left: 30, right: 30),
  272. child: Stack(
  273. children: <Widget>[
  274. Column(
  275. children: <Widget>[
  276. Container(
  277. margin: EdgeInsets.only(top: 25),
  278. width: 80,
  279. height: 80,
  280. child: Container(
  281. padding: EdgeInsets.all(5),
  282. width: 80,
  283. height: 80,
  284. decoration: BoxDecoration(
  285. borderRadius: BorderRadius.all(Radius.circular(80)),
  286. gradient: LinearGradient(
  287. begin: Alignment.topLeft,
  288. colors: [Color(0xFFFECF01), Color(0xFFD48E00)],
  289. ),
  290. boxShadow: [BoxShadow(color: Colors.black12, offset: Offset(2.0, 4.0), blurRadius: 4.0)]),
  291. child: CircleAvatar(backgroundImage: NetworkImage(rankList[0].userInfo.icon))),
  292. ),
  293. Container(
  294. padding: EdgeInsets.only(top: 7, bottom: 3),
  295. width: 60,
  296. child: Text(rankList[0].userInfo.nickname,
  297. style: TextStyle(color: Color(0xFF2E3049), fontSize: 14), overflow: TextOverflow.ellipsis, textAlign: TextAlign.center),
  298. ),
  299. Row(
  300. children: <Widget>[
  301. Padding(
  302. padding: EdgeInsets.only(right: 2),
  303. child: Image.asset('images/icon_jinbi_da_bai.png', width: 20),
  304. ),
  305. Text(rankList[0].bonus.toString(), style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500))
  306. ],
  307. )
  308. ],
  309. ),
  310. Positioned(top: 0, left: 24, child: Image.asset('images/icon_paihangbang_01.png', width: 32))
  311. ],
  312. ),
  313. ));
  314. }
  315. if (rankList.length > 1) {
  316. list.insert(
  317. 0,
  318. Container(
  319. margin: EdgeInsets.only(top: 25),
  320. child: Stack(
  321. children: <Widget>[
  322. Column(
  323. children: <Widget>[
  324. Container(
  325. margin: EdgeInsets.only(top: 25),
  326. width: 70,
  327. height: 70,
  328. child: Stack(
  329. children: <Widget>[
  330. Container(
  331. padding: EdgeInsets.all(5),
  332. width: 70,
  333. height: 70,
  334. decoration: BoxDecoration(
  335. borderRadius: BorderRadius.all(Radius.circular(70)),
  336. gradient: LinearGradient(
  337. begin: Alignment.topLeft,
  338. colors: [Color(0xFFE3E3E3), Color(0xFFC5C5C5)],
  339. ),
  340. boxShadow: [BoxShadow(color: Colors.black12, offset: Offset(2.0, 4.0), blurRadius: 4.0)]),
  341. child: CircleAvatar(backgroundImage: NetworkImage(rankList[1].userInfo.icon))),
  342. ],
  343. ),
  344. ),
  345. Container(
  346. padding: EdgeInsets.only(top: 7, bottom: 3),
  347. width: 60,
  348. child: Text(
  349. rankList[1].userInfo.nickname,
  350. style: TextStyle(color: Color(0xFF2E3049), fontSize: 14),
  351. overflow: TextOverflow.ellipsis,
  352. textAlign: TextAlign.center,
  353. ),
  354. ),
  355. Row(
  356. children: <Widget>[
  357. Padding(
  358. padding: EdgeInsets.only(right: 2),
  359. child: Image.asset('images/icon_jinbi_da_bai.png', width: 20),
  360. ),
  361. Text(rankList[1].bonus.toString(), style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500))
  362. ],
  363. )
  364. ],
  365. ),
  366. Positioned(top: 0, left: 19, child: Image.asset('images/icon_paihangbang_02.png', width: 32))
  367. ],
  368. )));
  369. }
  370. if (rankList.length > 2) {
  371. list.add(Container(
  372. margin: EdgeInsets.only(top: 25),
  373. child: Stack(
  374. children: <Widget>[
  375. Column(
  376. children: <Widget>[
  377. Container(
  378. width: 70,
  379. height: 70,
  380. margin: EdgeInsets.only(top: 25),
  381. child: Stack(
  382. children: <Widget>[
  383. Container(
  384. padding: EdgeInsets.all(5),
  385. width: 70,
  386. height: 70,
  387. decoration: BoxDecoration(
  388. borderRadius: BorderRadius.all(Radius.circular(70)),
  389. gradient: LinearGradient(
  390. begin: Alignment.topLeft,
  391. colors: [Color(0xFFF89E58), Color(0xFFE77023)],
  392. ),
  393. boxShadow: [BoxShadow(color: Colors.black12, offset: Offset(2.0, 4.0), blurRadius: 4.0)]),
  394. child: CircleAvatar(backgroundImage: NetworkImage(rankList[2].userInfo.icon))),
  395. ],
  396. ),
  397. ),
  398. Container(
  399. width: 60,
  400. padding: EdgeInsets.only(top: 7, bottom: 3),
  401. child: Text(rankList[2].userInfo.nickname,
  402. style: TextStyle(color: Color(0xFF2E3049), fontSize: 14), overflow: TextOverflow.ellipsis, textAlign: TextAlign.center),
  403. ),
  404. Row(
  405. children: <Widget>[
  406. Padding(
  407. padding: EdgeInsets.only(right: 2),
  408. child: Image.asset('images/icon_jinbi_da_bai.png', width: 20),
  409. ),
  410. Text(rankList[2].bonus.toString(), style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500))
  411. ],
  412. )
  413. ],
  414. ),
  415. Positioned(top: 0, left: 19, child: Image.asset('images/icon_paihangbang_03.png', width: 32))
  416. ],
  417. )));
  418. }
  419. if (rankList.length <= 1) {
  420. list.insert(
  421. 0,
  422. Container(
  423. // margin: EdgeInsets.only(top: 50),
  424. child: Container(
  425. width: 70,
  426. height: 70,
  427. ),
  428. ));
  429. }
  430. if (rankList.length <= 2) {
  431. list.add(Container(
  432. // margin: EdgeInsets.only(top: 50),
  433. child: Container(
  434. width: 70,
  435. height: 70,
  436. ),
  437. ));
  438. }
  439. return list;
  440. }
  441. }
  442. class RankItem extends StatelessWidget {
  443. RankItem(this.playerInfo, this.index, {this.color = 0, this.height = 66.0,this.border=true});
  444. final PlayerInfo playerInfo;
  445. final int index;
  446. final int color;
  447. final double height;
  448. final bool border;
  449. List<String> rankImgList = ['images/icon_paihangbang_01.png', 'images/icon_paihangbang_02.png', 'images/icon_paihangbang_03.png'];
  450. @override
  451. Widget build(BuildContext context) {
  452. return Container(
  453. height: height,
  454. padding: EdgeInsets.symmetric(horizontal: 15),
  455. decoration: BoxDecoration(
  456. // border: Border(bottom: BorderSide(width: 1, color: Colors.black26, style: BorderStyle.solid)),
  457. color: color == 0 ? Color(0xFF2E3049) : Color(color)),
  458. child: Container(
  459. decoration: BoxDecoration(
  460. border: Border(bottom: BorderSide(width: border?1:0, color: Colors.black26, style: BorderStyle.solid)),
  461. ),
  462. child: Row(
  463. children: <Widget>[
  464. playerInfo.rank < 100
  465. ? (playerInfo.rank < 4
  466. ? Padding(
  467. padding: EdgeInsets.only(right: 15),
  468. child: Image.asset(rankImgList[playerInfo.rank - 1]),
  469. )
  470. : Container(
  471. width: 30,
  472. height: 30,
  473. margin: EdgeInsets.only(right: 15),
  474. decoration: BoxDecoration(image: DecorationImage(image: AssetImage('images/icon_paihangbang_04_huangse.png'), fit: BoxFit.cover)),
  475. child: Text(
  476. playerInfo.rank.toString(),
  477. style: TextStyle(color: Color(0xFF15151D), fontSize: 12, fontWeight: FontWeight.w500, height: 2),
  478. textAlign: TextAlign.center,
  479. ),
  480. ))
  481. : Container(),
  482. Container(
  483. width: 36,
  484. height: 36,
  485. margin: EdgeInsets.only(right: 15),
  486. child: CircleAvatar(
  487. backgroundImage: NetworkImage(playerInfo.userInfo.icon),
  488. ),
  489. ),
  490. Expanded(
  491. flex: 1,
  492. child: Text(playerInfo.userInfo.nickname,
  493. style: TextStyle(color: Theme.of(context).primaryColor, fontSize: 14, height: 1.2), overflow: TextOverflow.ellipsis),
  494. ),
  495. Medal(playerInfo.getPlatinum(), '铂金'),
  496. Medal(playerInfo.getGold(), '金牌'),
  497. Medal(playerInfo.getSilver(), '银牌'),
  498. Medal(playerInfo.getBronze(), '铜牌'),
  499. ],
  500. ),
  501. ));
  502. }
  503. }
  504. class Medal extends StatelessWidget {
  505. Medal(this.value, this.name);
  506. final String value;
  507. final String name;
  508. // int platinum; //铂金
  509. // int gold;//金牌
  510. // int silver;//银牌
  511. // int bronze;//铜牌
  512. List<String> jiangpaiImgList = [
  513. 'images/jiangpai_bojin_xiao.png',
  514. 'images/jiangpai_jinpai_xiao.png',
  515. 'images/jiangpai_baiyin_xiao.png',
  516. 'images/jiangpai_qingtong_xiao.png'
  517. ];
  518. Map<String, dynamic> medalInfo = {
  519. "铂金": {"img": 'images/jiangpai_bojin_xiao.png'},
  520. "金牌": {"img": 'images/jiangpai_jinpai_xiao.png'},
  521. "银牌": {"img": 'images/jiangpai_baiyin_xiao.png'},
  522. "铜牌": {"img": 'images/jiangpai_qingtong_xiao.png'}
  523. };
  524. @override
  525. Widget build(BuildContext context) {
  526. return Container(
  527. width: 41,
  528. child: Row(
  529. children: <Widget>[
  530. Image.asset(medalInfo[name]["img"]),
  531. Text(
  532. value,
  533. style: TextStyle(color: Colors.white, fontSize: 14),
  534. )
  535. ],
  536. ),
  537. );
  538. }
  539. }
  540. class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  541. _SliverAppBarDelegate({
  542. @required this.minHeight,
  543. @required this.maxHeight,
  544. @required this.child,
  545. });
  546. final double minHeight;
  547. final double maxHeight;
  548. final Widget child;
  549. @override
  550. double get minExtent => minHeight;
  551. @override
  552. double get maxExtent => max(maxHeight, minHeight);
  553. @override
  554. Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
  555. return new SizedBox.expand(child: child);
  556. }
  557. @override
  558. bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
  559. return maxHeight != oldDelegate.maxHeight || minHeight != oldDelegate.minHeight || child != oldDelegate.child;
  560. }
  561. }