MatchPage.dart 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_swiper/flutter_swiper.dart';
  3. import 'package:cached_network_image/cached_network_image.dart';
  4. import 'package:flutter/cupertino.dart';
  5. import '../styles/totast.dart';
  6. import '../net/HttpManager.dart';
  7. import '../net/Result.dart';
  8. import 'TipList.dart';
  9. import 'package:flutter_redux/flutter_redux.dart';
  10. import '../redux/AppState.dart';
  11. import '../widget/LinearButton.dart';
  12. import '../model/BannerInfo.dart';
  13. import '../widget/ITextInput.dart';
  14. import '../widget/HouseItem.dart';
  15. import '../model/HouseInfo.dart';
  16. import 'OpenRoom.dart';
  17. import 'package:flutter_picker/flutter_picker.dart';
  18. import '../model/GameInfo.dart';
  19. import 'dart:async';
  20. import 'dart:convert';
  21. import 'dart:ui';
  22. import 'dart:math';
  23. class MatchPage extends StatefulWidget {
  24. @override
  25. _MatchPageState createState() => _MatchPageState();
  26. }
  27. class _MatchPageState extends State<MatchPage> with WidgetsBindingObserver {
  28. List<HouseInfo> houseList = [];
  29. int currentPage = 0;
  30. bool showBadge = false;
  31. int gameId = 0;
  32. String searchKey = '';
  33. bool scrollFlag = false;
  34. List<BannerInfo> bannerList = [];
  35. ScrollController _controller;
  36. List<GameInfo> gameList = [];
  37. String gameName = '全部游戏';
  38. bool isFirst = true;
  39. FocusNode _focusNode = new FocusNode();
  40. void showPicker(BuildContext context) {
  41. List<String> _list = [];
  42. for (var item in gameList) {
  43. _list.add(item.gameName);
  44. }
  45. String PickerData = json.encode(_list);
  46. Picker(
  47. confirmText: '确定',
  48. cancelText: '取消',
  49. adapter: PickerDataAdapter<String>(pickerdata: JsonDecoder().convert(PickerData)),
  50. changeToFirst: true,
  51. textAlign: TextAlign.left,
  52. columnPadding: const EdgeInsets.all(8.0),
  53. onConfirm: (Picker picker, List value) {
  54. setState(() {
  55. gameId = gameList[value[0]].id;
  56. gameName = gameList[value[0]].gameName;
  57. });
  58. }).showModal(this.context);
  59. }
  60. Future<void> getGame() async {
  61. // Toast.show(context, '加载中', -1, 'loading');
  62. Result res = await HttpManager.get('gameInfo/all');
  63. // Toast.hide();
  64. if (res.success) {
  65. List<GameInfo> _list = [];
  66. for (var item in res.data) {
  67. _list.add(GameInfo.fromJson(item));
  68. }
  69. setState(() {
  70. gameList = _list;
  71. });
  72. } else {}
  73. }
  74. Future<void> getUnreadMsg() async {
  75. Result res = await HttpManager.get('systemNotice/unread', data: {'userId': StoreProvider.of<AppState>(context).state.userInfo.id, 'statusFlag': 0});
  76. if (res.success && res.data != null) {
  77. if (res.data > 0) {
  78. setState(() {
  79. showBadge = true;
  80. });
  81. } else {
  82. setState(() {
  83. showBadge = false;
  84. });
  85. }
  86. }
  87. }
  88. Future<void> getRoomInfo() async {
  89. print('获取房间');
  90. Map<String, dynamic> data = {'currentPage': currentPage, 'pageNumber': 20, 'myUserId': StoreProvider.of<AppState>(context).state.userInfo.id};
  91. data['advancedQuery'] = '';
  92. if (gameId != 0) {
  93. data['gameId'] = gameId;
  94. }
  95. data['searchKey'] = searchKey;
  96. List<HouseInfo> _allList = houseList;
  97. if (currentPage == 1) {
  98. _allList = [];
  99. }
  100. if (StoreProvider.of<AppState>(context).state.userInfo.recommender != null) {
  101. data['recommender'] = StoreProvider.of<AppState>(context).state.userInfo.recommender;
  102. }
  103. Result res = await HttpManager.get('houseInfo/page', data: data);
  104. if (res.success && res.data['pp'] != null) {
  105. for (var item in res.data['pp']) {
  106. HouseInfo _temHouse = HouseInfo.fromJson(item);
  107. _allList.add(_temHouse);
  108. }
  109. if (res.data['page']['currentPage'] < res.data['page']['totalPage']) {
  110. scrollFlag = true;
  111. } else {
  112. scrollFlag = false;
  113. }
  114. } else {}
  115. setState(() {
  116. houseList = _allList;
  117. });
  118. }
  119. Future<void> search(String text) async {
  120. if (text != searchKey) {
  121. currentPage = 1;
  122. searchKey = text;
  123. getRoomInfo();
  124. }
  125. }
  126. Future<void> getBannerInfo() async {
  127. List<BannerInfo> _bannerList = [];
  128. Toast.show(context, '加载中', -1, 'loading');
  129. Result res = await HttpManager.get('bannerInfo/all');
  130. Toast.hide();
  131. if (res.success && res.data != null) {
  132. for (var item in res.data) {
  133. BannerInfo banner = BannerInfo.fromJson(item);
  134. _bannerList.add(banner);
  135. }
  136. setState(() {
  137. bannerList = _bannerList;
  138. });
  139. }
  140. }
  141. @override
  142. void initState() {
  143. super.initState();
  144. bannerList = [];
  145. _controller = ScrollController();
  146. // gameList.add(GameInfo.fromJson({"id": 0, "gameName": '全部游戏'}));
  147. _controller.addListener(() {
  148. if (_controller.position.pixels == _controller.position.maxScrollExtent) {
  149. if (scrollFlag) {
  150. setState(() {
  151. currentPage++;
  152. });
  153. getRoomInfo();
  154. }
  155. }
  156. });
  157. Future.delayed(Duration.zero, () {
  158. getBannerInfo();
  159. getGame();
  160. getRoomInfo();
  161. });
  162. }
  163. @override
  164. void dispose() {
  165. super.dispose();
  166. }
  167. @override
  168. Widget build(BuildContext context) {
  169. return WillPopScope(
  170. child: GestureDetector(
  171. behavior: HitTestBehavior.translucent,
  172. child: Scaffold(
  173. appBar: AppBar(
  174. title: Text('赛事'),
  175. centerTitle: true,
  176. leading: Material(
  177. color: Colors.transparent,
  178. child: Builder(
  179. builder: (context) => InkWell(
  180. onTap: () async {
  181. bool result = await Navigator.push(context, CupertinoPageRoute(builder: (context) => TipList()));
  182. if (result) {
  183. getUnreadMsg();
  184. }
  185. },
  186. child: Image.asset('images/home_icon_xiaoxi.png'),
  187. ),
  188. ),
  189. ),
  190. actions: <Widget>[
  191. Container(
  192. width: 102,
  193. padding: EdgeInsets.all(15),
  194. child: LinearButton(
  195. btntext: '发起比赛',
  196. textColor: Color(0xFFA2423E),
  197. btnHeight: 26.0,
  198. colorList: [Color(0xFFFFE77C), Color(0xFFFFE77C)],
  199. textSize: 12.0,
  200. onTapHomeMenu: () => {Navigator.push(context, CupertinoPageRoute(builder: (context) => OpenRoom(roomFlag: '0')))},
  201. ),
  202. )
  203. ],
  204. ),
  205. body: Container(
  206. color: Color(0xFF2E3049),
  207. height: double.infinity,
  208. width: double.infinity,
  209. child: RefreshIndicator(
  210. color: Theme.of(context).primaryColor,
  211. backgroundColor: Colors.white,
  212. displacement: 10,
  213. onRefresh: () async {
  214. await Future.delayed(const Duration(seconds: 1));
  215. gameId = 0;
  216. currentPage = 1;
  217. searchKey = '';
  218. getRoomInfo();
  219. // getBannerInfo();
  220. getGame();
  221. },
  222. child: CustomScrollView(
  223. physics: AlwaysScrollableScrollPhysics(),
  224. controller: _controller,
  225. slivers: <Widget>[
  226. SliverToBoxAdapter(
  227. child: Container(
  228. width: double.infinity,
  229. height: 200,
  230. child: new Swiper(
  231. itemBuilder: (BuildContext context, int index) {
  232. return Image.network(
  233. bannerList[index].imageUrl,
  234. fit: BoxFit.fill,
  235. );
  236. },
  237. itemCount: bannerList.length,
  238. loop: false,
  239. autoplay: true,
  240. autoplayDelay: 5000,
  241. pagination: SwiperCustomPagination(builder: (BuildContext context, SwiperPluginConfig config) {
  242. Color activeColor = Color(0xFFD4504B);
  243. Color color = Colors.white;
  244. List<Widget> list = [];
  245. int itemCount = config.itemCount;
  246. int activeIndex = config.activeIndex;
  247. for (int i = 0; i < itemCount; ++i) {
  248. bool active = i == activeIndex;
  249. list.add(
  250. Container(
  251. key: Key("pagination_$i"),
  252. margin:EdgeInsets.symmetric(vertical: 3,horizontal: 2),
  253. child: Container(
  254. width: active ? 8 : 3,
  255. height: 3,
  256. decoration: BoxDecoration(color: active ? activeColor : color, borderRadius: BorderRadius.all(Radius.circular(3))),
  257. )),
  258. );
  259. }
  260. return Container(
  261. margin: EdgeInsets.only(top: 186),
  262. child: Row(
  263. mainAxisAlignment: MainAxisAlignment.center,
  264. children: list,
  265. ),
  266. );
  267. })),
  268. ),
  269. ),
  270. SliverPersistentHeader(
  271. pinned: true, //是否固定在顶部
  272. floating: true,
  273. delegate: _SliverAppBarDelegate(
  274. minHeight: 60, //收起的高度
  275. maxHeight: 60, //展开的最大高度
  276. child: Container(
  277. color: Color(0xFF2E3049),
  278. height: 60,
  279. padding: EdgeInsets.symmetric(vertical: 10, horizontal: 15),
  280. child: Container(
  281. decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(4))),
  282. child: Row(
  283. children: <Widget>[
  284. Container(
  285. width: 10,
  286. ),
  287. ImageIcon(
  288. AssetImage('images/home_icon_sousuo.png'),
  289. color: Color(0xFF727785),
  290. ),
  291. Expanded(
  292. flex: 1,
  293. child: Container(
  294. height: 34,
  295. decoration: BoxDecoration(
  296. color: Colors.white,
  297. borderRadius: BorderRadius.all(Radius.circular(100)),
  298. ),
  299. child: ITextField(
  300. hintText: '搜索竞赛房间',
  301. inputBorder: InputBorder.none,
  302. hintStyle: TextStyle(fontSize: 13, color: Color(0xFFB1B5C0), height: 1.2),
  303. textStyle: TextStyle(color: Colors.black),
  304. contentPadding: EdgeInsets.symmetric(vertical: 4, horizontal: 4),
  305. fieldCallBack: (content) {
  306. search(content);
  307. _focusNode.unfocus();
  308. },
  309. focusNode: _focusNode,
  310. counterStyle: TextStyle(color: Color(0xFF9BA0AE), fontSize: 0),
  311. textInputAction: TextInputAction.search,
  312. fileOnTap: () {
  313. print('选择input');
  314. if (_controller.position.pixels < 200) {
  315. _controller.animateTo(200, duration: Duration(milliseconds: 300), curve: Curves.ease);
  316. }
  317. }),
  318. ),
  319. ),
  320. Container(
  321. width: 1,
  322. height: 10,
  323. color: Color(0xFFB1B5C0),
  324. ),
  325. Container(
  326. width: 99,
  327. child: InkWell(
  328. onTap: () {
  329. showPicker(context);
  330. },
  331. child: Row(
  332. mainAxisAlignment: MainAxisAlignment.center,
  333. children: <Widget>[
  334. Expanded(
  335. flex: 1,
  336. child: Container(
  337. padding: EdgeInsets.only(left: 5),
  338. alignment: Alignment.center,
  339. child: Text(
  340. gameName,
  341. style: TextStyle(color: Color(0xFFB1B5C0)),
  342. overflow: TextOverflow.ellipsis,
  343. ),
  344. ),
  345. ),
  346. Image.asset('images/icon_zhankai_huise.png'),
  347. Container(
  348. width: 5,
  349. )
  350. ],
  351. )))
  352. ],
  353. ),
  354. ),
  355. )),
  356. ),
  357. SliverFixedExtentList(
  358. itemExtent: houseList.isEmpty ? 300 : 90,
  359. delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
  360. if (houseList.isEmpty) {
  361. return Container(
  362. padding: EdgeInsets.only(top: 105),
  363. child: Column(
  364. children: <Widget>[
  365. Image.asset('images/icon_kong.png'),
  366. Text('暂时没有此房间哦~', style: TextStyle(fontSize: 14, color: Theme.of(context).primaryColor.withOpacity(0.3)))
  367. ],
  368. ),
  369. );
  370. } else if (index == houseList.length) {
  371. return Text('更多房间敬请期待...', style: TextStyle(color: Colors.grey, fontSize: 13, height: 3), textAlign: TextAlign.center);
  372. }
  373. return HouseItem(houseList[index], houseList[index].gameInfo);
  374. }, childCount: houseList.length + 1),
  375. )
  376. ],
  377. ),
  378. ),
  379. )),
  380. onTap: () {
  381. _focusNode.unfocus();
  382. },
  383. ),
  384. onWillPop: () {
  385. if (isFirst) {
  386. isFirst = false;
  387. Toast.show(context, '再次点击退出程序', 1500, 'info');
  388. Timer(Duration(seconds: 2), () {
  389. isFirst = true;
  390. });
  391. return Future.value(false);
  392. } else {
  393. return Future.value(true);
  394. }
  395. },
  396. );
  397. }
  398. List<Widget> _houseList(houselist) {
  399. List<Widget> list = [];
  400. for (var i = 0; i < houselist.length; i++) {
  401. list.add(HouseItem(houselist[i], houselist[i].gameInfo));
  402. }
  403. return list;
  404. }
  405. }
  406. class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  407. _SliverAppBarDelegate({
  408. @required this.minHeight,
  409. @required this.maxHeight,
  410. @required this.child,
  411. });
  412. final double minHeight;
  413. final double maxHeight;
  414. final Widget child;
  415. @override
  416. double get minExtent => minHeight;
  417. @override
  418. double get maxExtent => max(maxHeight, minHeight);
  419. @override
  420. Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
  421. return new SizedBox.expand(child: child);
  422. }
  423. @override
  424. bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
  425. return maxHeight != oldDelegate.maxHeight || minHeight != oldDelegate.minHeight || child != oldDelegate.child;
  426. }
  427. }