MatchPage.dart 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. import 'dart:io';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/painting.dart';
  4. import 'package:flutter_swiper/flutter_swiper.dart';
  5. import 'package:shared_preferences/shared_preferences.dart';
  6. import 'package:flutter/cupertino.dart';
  7. import '../styles/totast.dart';
  8. import '../net/HttpManager.dart';
  9. import '../net/Result.dart';
  10. import 'TipList.dart';
  11. import 'package:flutter_redux/flutter_redux.dart';
  12. import '../redux/AppState.dart';
  13. import '../widget/LinearButton.dart';
  14. import '../model/BannerInfo.dart';
  15. import '../widget/HouseItem.dart';
  16. import '../model/HouseInfo.dart';
  17. import 'package:flutter_picker/flutter_picker.dart';
  18. import 'CompetitionInformation.dart';
  19. import '../model/GameInfo.dart';
  20. import 'dart:async';
  21. import 'dart:convert';
  22. import 'dart:ui';
  23. import 'dart:math';
  24. import 'SelectRoom.dart';
  25. import '../model/PhoneInfo.dart';
  26. import 'PhoneLogin.dart';
  27. class MatchPage extends StatefulWidget {
  28. @override
  29. _MatchPageState createState() => _MatchPageState();
  30. }
  31. class _MatchPageState extends State<MatchPage> with WidgetsBindingObserver {
  32. List<HouseInfo> houseList = [];
  33. int currentPage = 0;
  34. bool showBadge = false;
  35. int gameId = 0;
  36. String searchKey = '';
  37. bool scrollFlag = false;
  38. List<BannerInfo> bannerList = [];
  39. ScrollController _controller;
  40. List<GameInfo> gameList = [];
  41. String gameName = '全部游戏';
  42. FocusNode _focusNode = new FocusNode();
  43. List<PhoneInfo> phoneList = [];
  44. int tipNum = 0;
  45. bool showMoreRoom = false;
  46. bool isFinish = false;
  47. Timer timer;
  48. Future<void> getUnreadMsg() async {
  49. print('检查信息');
  50. Result res = await HttpManager.get('systemNotice/unread', data: {'userId': StoreProvider.of<AppState>(context).state.userInfo.id, 'statusFlag': 0});
  51. if (res.success && res.data != null) {
  52. setState(() {
  53. tipNum = res.data;
  54. });
  55. if (res.data > 0) {
  56. setState(() {
  57. showBadge = true;
  58. });
  59. } else {
  60. setState(() {
  61. showBadge = false;
  62. });
  63. }
  64. }
  65. }
  66. //展示通知
  67. void showNotice() {
  68. Navigator.of(context).push(PageRouteBuilder(
  69. opaque: false,
  70. transitionDuration: Duration(milliseconds: 300),
  71. transitionsBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
  72. return FadeTransition(
  73. opacity: CurvedAnimation(parent: animation, curve: Curves.linear),
  74. child: child,
  75. );
  76. },
  77. pageBuilder: (BuildContext context, _, __) {
  78. return CompetitionInformation();
  79. }));
  80. }
  81. void showPicker(BuildContext context) {
  82. List<String> _list = [];
  83. for (var item in gameList) {
  84. _list.add(item.gameName);
  85. }
  86. String PickerData = json.encode(_list);
  87. Picker(
  88. confirmText: '确定',
  89. cancelText: '取消',
  90. adapter: PickerDataAdapter<String>(pickerdata: JsonDecoder().convert(PickerData)),
  91. changeToFirst: true,
  92. textAlign: TextAlign.left,
  93. columnPadding: const EdgeInsets.all(8.0),
  94. onConfirm: (Picker picker, List value) {
  95. setState(() {
  96. gameId = gameList[value[0]].id;
  97. gameName = gameList[value[0]].gameName;
  98. });
  99. }).showModal(this.context);
  100. }
  101. Future<void> getGame() async {
  102. // Toast.show(context, '加载中', -1, 'loading');
  103. Result res = await HttpManager.get('gameInfo/all');
  104. // Toast.hide();
  105. if (res.success) {
  106. List<GameInfo> _list = [];
  107. for (var item in res.data) {
  108. _list.add(GameInfo.fromJson(item));
  109. }
  110. setState(() {
  111. gameList = _list;
  112. });
  113. } else {}
  114. }
  115. Future<void> getRoomInfo() async {
  116. print('获取房间');
  117. Map<String, dynamic> data = {
  118. 'currentPage': currentPage,
  119. 'pageNumber': 20,
  120. 'statusStr': '0,2',
  121. 'myUserId': StoreProvider.of<AppState>(context).state.userInfo.id
  122. };
  123. data['advancedQuery'] = '';
  124. if (gameId != 0) {
  125. data['gameId'] = gameId;
  126. }
  127. data['searchKey'] = searchKey;
  128. List<HouseInfo> _allList = houseList;
  129. if (currentPage == 1) {
  130. _allList = [];
  131. }
  132. if (StoreProvider.of<AppState>(context).state.userInfo.recommender != null) {
  133. data['recommender'] = StoreProvider.of<AppState>(context).state.userInfo.recommender;
  134. }
  135. Result res = await HttpManager.get('houseInfo/page', data: data);
  136. if (res.success && res.data['pp'] != null) {
  137. for (var item in res.data['pp']) {
  138. HouseInfo _temHouse = HouseInfo.fromJson(item);
  139. _allList.add(_temHouse);
  140. }
  141. if (res.data['page']['currentPage'] < res.data['page']['totalPage']) {
  142. scrollFlag = true;
  143. } else {
  144. setState(() {
  145. isFinish = true;
  146. });
  147. scrollFlag = false;
  148. }
  149. } else {}
  150. setState(() {
  151. houseList = _allList;
  152. });
  153. }
  154. Future<void> search(String text) async {
  155. if (text != searchKey) {
  156. currentPage = 1;
  157. searchKey = text;
  158. getRoomInfo();
  159. }
  160. }
  161. Future<void> getBannerInfo() async {
  162. List<BannerInfo> _bannerList = [];
  163. Toast.show(context, '加载中', -1, 'loading');
  164. Result res = await HttpManager.get('bannerInfo/all');
  165. Toast.hide();
  166. if (res.success && res.data != null) {
  167. for (var item in res.data) {
  168. BannerInfo banner = BannerInfo.fromJson(item);
  169. _bannerList.add(banner);
  170. }
  171. setState(() {
  172. bannerList = _bannerList;
  173. });
  174. }
  175. }
  176. Future<void> getPhoneInfo() async {
  177. List<PhoneInfo> _phoneList = [];
  178. Result res = await HttpManager.get('phoneInfo/all');
  179. if (res.success && res.data != null) {
  180. for (var item in res.data) {
  181. PhoneInfo phone = PhoneInfo.fromJson(item);
  182. _phoneList.add(phone);
  183. }
  184. setState(() {
  185. phoneList = _phoneList;
  186. });
  187. }
  188. final prefs = await SharedPreferences.getInstance();
  189. var now = new DateTime.now();
  190. var timeStr = now.year.toString() + '/' + now.month.toString() + '/' + now.day.toString();
  191. prefs.setString('showPhoneInfo', timeStr);
  192. Navigator.of(context).push(
  193. PageRouteBuilder(
  194. opaque: false,
  195. transitionDuration: Duration(milliseconds: 300),
  196. transitionsBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
  197. return FadeTransition(
  198. opacity: CurvedAnimation(parent: animation, curve: Curves.linear),
  199. child: child,
  200. );
  201. },
  202. pageBuilder: (BuildContext context, _, __) {
  203. return PhoneLogin(
  204. // text: '部分手机自动设置了省电策略,会将我们的app在游戏进程中从后台停掉,为了你的正常比赛,请点击你的手机型号查看具体设置',
  205. phoneList: phoneList,
  206. );
  207. },
  208. ),
  209. );
  210. }
  211. @override
  212. void initState() {
  213. super.initState();
  214. bannerList = [];
  215. _controller = ScrollController();
  216. // gameList.add(GameInfo.fromJson({"id": 0, "gameName": '全部游戏'}));
  217. _controller.addListener(() {
  218. if (_controller.position.pixels == _controller.position.maxScrollExtent) {
  219. print('底部。。。');
  220. setState(() {
  221. showMoreRoom = true;
  222. });
  223. if (scrollFlag) {
  224. setState(() {
  225. currentPage++;
  226. });
  227. getRoomInfo();
  228. } else {
  229. Future.delayed(Duration(seconds: 2), () async {
  230. setState(() {
  231. showMoreRoom = false;
  232. });
  233. });
  234. }
  235. }
  236. });
  237. Future.delayed(Duration.zero, () async {
  238. getUnreadMsg();
  239. getBannerInfo();
  240. getGame();
  241. getRoomInfo();
  242. if (timer != null) {
  243. timer.cancel();
  244. }
  245. timer = Timer.periodic(Duration(seconds: 2), (timer) {
  246. getUnreadMsg();
  247. });
  248. });
  249. }
  250. @override
  251. void didChangeAppLifecycleState(AppLifecycleState state) {
  252. if (state == AppLifecycleState.resumed) {
  253. getUnreadMsg();
  254. }
  255. }
  256. @override
  257. void dispose() {
  258. if (timer != null) {
  259. timer.cancel();
  260. }
  261. super.dispose();
  262. }
  263. @override
  264. Widget build(BuildContext context) {
  265. return GestureDetector(
  266. behavior: HitTestBehavior.translucent,
  267. child: Scaffold(
  268. appBar: AppBar(
  269. title: Text('赛事'),
  270. centerTitle: true,
  271. leading: Material(
  272. color: Colors.transparent,
  273. child: Builder(
  274. builder: (context) => InkWell(
  275. onTap: () async {
  276. if (timer != null) {
  277. timer.cancel();
  278. }
  279. bool result = await Navigator.push(context, CupertinoPageRoute(builder: (context) => TipList()));
  280. if (result) {
  281. timer = Timer.periodic(Duration(seconds: 2), (timer) {
  282. getUnreadMsg();
  283. });
  284. }
  285. },
  286. child: Container(
  287. width: 30,
  288. height: 30,
  289. child: Stack(
  290. children: <Widget>[
  291. Center(
  292. child: Image.asset('images/home_icon_xiaoxi.png'),
  293. ),
  294. showBadge
  295. ? Positioned(
  296. right: 10,
  297. top: 12,
  298. child: Container(
  299. padding: EdgeInsets.all(1),
  300. decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(100))),
  301. child: Center(
  302. child: Container(
  303. padding: EdgeInsets.symmetric(horizontal: 3),
  304. height: 12,
  305. decoration: BoxDecoration(color: Color(0xFFD4504B), borderRadius: BorderRadius.all(Radius.circular(12))),
  306. child: Center(
  307. child: Text('${tipNum}', style: TextStyle(color: Colors.white, fontSize: 10)),
  308. ),
  309. ),
  310. ),
  311. ),
  312. )
  313. : Container()
  314. ],
  315. ),
  316. ),
  317. ),
  318. ),
  319. ),
  320. actions: <Widget>[
  321. Platform.isIOS
  322. ? Container()
  323. : Container(
  324. width: 102,
  325. padding: EdgeInsets.all(15),
  326. child: LinearButton(
  327. btntext: '配置帮助',
  328. textColor: Color(0xFF2E3049),
  329. btnHeight: 26.0,
  330. colorList: [Color(0xFFFFB726), Color(0xFFFFB726)],
  331. textSize: 12.0,
  332. onTapHomeMenu: () {
  333. // showNotice();
  334. getPhoneInfo();
  335. },
  336. ),
  337. )
  338. ],
  339. ),
  340. body: Container(
  341. color: Color(0xFF2E3049),
  342. height: double.infinity,
  343. width: double.infinity,
  344. child: RefreshIndicator(
  345. color: Theme.of(context).primaryColor,
  346. backgroundColor: Colors.white,
  347. displacement: 10,
  348. onRefresh: () async {
  349. await Future.delayed(const Duration(seconds: 1));
  350. gameId = 0;
  351. currentPage = 1;
  352. searchKey = '';
  353. getRoomInfo();
  354. // getBannerInfo();
  355. getGame();
  356. },
  357. child: CustomScrollView(
  358. physics: AlwaysScrollableScrollPhysics(),
  359. controller: _controller,
  360. slivers: <Widget>[
  361. SliverToBoxAdapter(
  362. child: Container(
  363. width: double.infinity,
  364. height: 200,
  365. child: new Swiper(
  366. itemBuilder: (BuildContext context, int index) {
  367. return Image.network(
  368. bannerList[index].imageUrl,
  369. fit: BoxFit.fill,
  370. );
  371. },
  372. itemCount: bannerList.length,
  373. loop: false,
  374. autoplay: true,
  375. autoplayDelay: 5000,
  376. pagination: SwiperCustomPagination(builder: (BuildContext context, SwiperPluginConfig config) {
  377. Color activeColor = Color(0xFFD4504B);
  378. Color color = Colors.white;
  379. List<Widget> list = [];
  380. int itemCount = config.itemCount;
  381. int activeIndex = config.activeIndex;
  382. for (int i = 0; i < itemCount; ++i) {
  383. bool active = i == activeIndex;
  384. list.add(
  385. Container(
  386. key: Key("pagination_$i"),
  387. margin: EdgeInsets.symmetric(vertical: 3, horizontal: 2),
  388. child: Container(
  389. width: active ? 8 : 3,
  390. height: 3,
  391. decoration: BoxDecoration(color: active ? activeColor : color, borderRadius: BorderRadius.all(Radius.circular(3))),
  392. )),
  393. );
  394. }
  395. return Container(
  396. margin: EdgeInsets.only(top: 186),
  397. child: Row(
  398. mainAxisAlignment: MainAxisAlignment.center,
  399. children: list,
  400. ),
  401. );
  402. })),
  403. ),
  404. ),
  405. SliverPersistentHeader(
  406. pinned: true, //是否固定在顶部
  407. floating: true,
  408. delegate: _SliverAppBarDelegate(
  409. minHeight: 60, //收起的高度
  410. maxHeight: 60, //展开的最大高度
  411. child: InkWell(
  412. onTap: () {
  413. Navigator.push(context, CupertinoPageRoute(builder: (context) => SelectRoom()));
  414. },
  415. child: Container(
  416. color: Color(0xFF2E3049),
  417. height: 60,
  418. padding: EdgeInsets.symmetric(vertical: 10, horizontal: 15),
  419. child: Container(
  420. decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(4))),
  421. child: Row(
  422. children: <Widget>[
  423. Container(
  424. width: 10,
  425. ),
  426. ImageIcon(
  427. AssetImage('images/home_icon_sousuo.png'),
  428. color: Color(0xFF727785),
  429. ),
  430. Expanded(
  431. flex: 1,
  432. child: Container(
  433. decoration: BoxDecoration(
  434. color: Colors.white,
  435. borderRadius: BorderRadius.all(Radius.circular(100)),
  436. ),
  437. child: Text('搜索竞赛房间', style: TextStyle(color: Color(0xFF9BA0AE), fontSize: 13)),
  438. ),
  439. ),
  440. Container(
  441. width: 1,
  442. height: 10,
  443. color: Color(0xFFB1B5C0),
  444. ),
  445. Container(
  446. width: 99,
  447. child: Row(
  448. mainAxisAlignment: MainAxisAlignment.center,
  449. children: <Widget>[
  450. Expanded(
  451. flex: 1,
  452. child: Container(
  453. padding: EdgeInsets.only(left: 5),
  454. alignment: Alignment.center,
  455. child: Text(
  456. gameName,
  457. style: TextStyle(color: Color(0xFFB1B5C0)),
  458. overflow: TextOverflow.ellipsis,
  459. ),
  460. ),
  461. ),
  462. Image.asset('images/icon_zhankai_huise.png'),
  463. Container(
  464. width: 5,
  465. )
  466. ],
  467. ))
  468. ],
  469. ),
  470. ),
  471. ))),
  472. ),
  473. SliverFixedExtentList(
  474. itemExtent: houseList.isEmpty ? 300 : 90,
  475. delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
  476. if (houseList.isEmpty) {
  477. return InkWell(
  478. child: Container(
  479. padding: EdgeInsets.only(top: 105),
  480. child: Column(
  481. children: <Widget>[
  482. Image.asset('images/icon_kong.png'),
  483. Text('暂时没有此房间哦~', style: TextStyle(fontSize: 14, color: Theme.of(context).primaryColor.withOpacity(0.3)))
  484. ],
  485. ),
  486. ),
  487. onTap: () {
  488. _focusNode.unfocus();
  489. },
  490. );
  491. } else if (index == houseList.length) {
  492. return Text(isFinish ? '更多房间敬请期待...' : '加载中...',
  493. style: TextStyle(color: Colors.grey, fontSize: 13, height: 3), textAlign: TextAlign.center);
  494. }
  495. return HouseItem(houseList[index], houseList[index].gameInfo, isHome: true, isNext: !_focusNode.hasFocus, onTapHomeMenu: () {
  496. setState(() {
  497. _focusNode.unfocus();
  498. });
  499. }, onBack: () {
  500. getUnreadMsg();
  501. if (timer != null) {
  502. timer.cancel();
  503. }
  504. timer = Timer.periodic(Duration(seconds: 2), (timer) {
  505. getUnreadMsg();
  506. });
  507. }, onNext: () {
  508. if (timer != null) {
  509. timer.cancel();
  510. }
  511. });
  512. }, childCount: (houseList.length != 0 && (houseList.length < 5 || !showMoreRoom)) ? houseList.length : houseList.length + 1),
  513. ),
  514. SliverToBoxAdapter(
  515. child: Container(
  516. height: 30,
  517. ),
  518. )
  519. ],
  520. ),
  521. ),
  522. )),
  523. onTap: () {
  524. _focusNode.unfocus();
  525. },
  526. );
  527. }
  528. List<Widget> _houseList(houselist) {
  529. List<Widget> list = [];
  530. for (var i = 0; i < houselist.length; i++) {
  531. list.add(HouseItem(houselist[i], houselist[i].gameInfo));
  532. }
  533. return list;
  534. }
  535. }
  536. class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  537. _SliverAppBarDelegate({
  538. @required this.minHeight,
  539. @required this.maxHeight,
  540. @required this.child,
  541. });
  542. final double minHeight;
  543. final double maxHeight;
  544. final Widget child;
  545. @override
  546. double get minExtent => minHeight;
  547. @override
  548. double get maxExtent => max(maxHeight, minHeight);
  549. @override
  550. Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
  551. return new SizedBox.expand(child: child);
  552. }
  553. @override
  554. bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
  555. return maxHeight != oldDelegate.maxHeight || minHeight != oldDelegate.minHeight || child != oldDelegate.child;
  556. }
  557. }
  558. typedef OnTapHomeMenu = void Function();