RankList.dart 20 KB

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