RankList.dart 20 KB

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