Hibok
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

715 Zeilen
24 KiB

  1. import 'package:chat/data/UserData.dart';
  2. import 'package:chat/data/WebData.dart';
  3. import 'package:chat/data/constants.dart';
  4. import 'package:chat/generated/i18n.dart';
  5. import 'package:chat/home/SearchPage.dart';
  6. import 'package:chat/models/ref_name_provider.dart';
  7. import 'package:chat/utils/CustomUI.dart';
  8. import 'package:chat/utils/DropDownMemu.dart';
  9. import 'package:chat/utils/HttpUtil.dart';
  10. import 'package:chat/utils/MessageMgr.dart';
  11. import 'package:chat/utils/Toggle.dart';
  12. import 'package:chat/utils/TokenMgr.dart';
  13. import 'package:chat/utils/UserCard.dart';
  14. import 'package:chat/utils/screen.dart';
  15. import 'package:dio/dio.dart';
  16. import 'package:flutter/cupertino.dart';
  17. import 'package:flutter/material.dart';
  18. import 'package:location_permissions/location_permissions.dart';
  19. import 'package:provider/provider.dart';
  20. import 'package:pull_to_refresh/pull_to_refresh.dart';
  21. class DisCoverPage extends StatefulWidget {
  22. DisCoverPage({Key key}) : super(key: key);
  23. _DisCoverPageState createState() => _DisCoverPageState();
  24. }
  25. class _DisCoverPageState extends State<DisCoverPage>
  26. with TickerProviderStateMixin {
  27. TabController sameTabCtrl;
  28. TabController diffTabCtrl;
  29. RefreshController _scrollControllerNear =
  30. RefreshController(initialRefresh: true);
  31. RefreshController _scrollControllerNew =
  32. RefreshController(initialRefresh: true);
  33. RefreshController _scrollControllerApply =
  34. RefreshController(initialRefresh: true);
  35. RefreshController _scrollControllerVIP =
  36. RefreshController(initialRefresh: true);
  37. bool isPerformingRequest = false;
  38. Map listMap = {
  39. 1: {'list': [], 'page': 1, 'control': null},
  40. 2: {'list': [], 'page': 1, 'control': null},
  41. 3: {'list': [], 'page': 1, 'control': null},
  42. 4: {'list': [], 'page': 1, 'control': null},
  43. }; //不同类别的数据
  44. int type = 1;
  45. int rows = 20;
  46. bool isLoading = false; //是否正在加载数据
  47. static const SEPARATE_SIZE = 20.0;
  48. bool isOnline = false;
  49. bool isWomen = UserData().isMan();
  50. String search = '1';
  51. String titleStr = '';
  52. GZXDropdownMenuController _dropdownMenuController =
  53. GZXDropdownMenuController();
  54. //获取新的数据
  55. void getNewData() {
  56. listMap[type]['page'] = 1;
  57. getData((data) {
  58. listMap[type]['list'].clear();
  59. if (data != null) {
  60. listMap[type]['list'].addAll(data);
  61. }
  62. if (mounted) {
  63. setState(() {});
  64. }
  65. });
  66. }
  67. void _onLoading() async {
  68. listMap[type]['page']++;
  69. getData((data) {
  70. if (data == null || data.length == 0) {
  71. listMap[type]['page']--;
  72. listMap[type]['control'].loadNoData();
  73. } else {
  74. listMap[type]['list'].addAll(data);
  75. listMap[type]['control'].loadComplete();
  76. }
  77. if (mounted) {
  78. setState(() {});
  79. }
  80. });
  81. }
  82. void getData(callback) async {
  83. var data = {
  84. "userId": UserData().basicInfo.userId,
  85. "type": type,
  86. "search": search,
  87. };
  88. data['sign'] = TokenMgr().getSign(data);
  89. data['lng'] = UserData().longitude;
  90. data['lat'] = UserData().latitude;
  91. data['page'] = listMap[type]['page'];
  92. data['rows'] = rows;
  93. data['sex'] = isWomen ? 2 : 1;
  94. data['online'] = isOnline ? 1 : 0;
  95. Response res = await HttpUtil().post('user/main/interface', data: data);
  96. listMap[type]['control'].refreshCompleted();
  97. isLoading = false;
  98. if (res == null) {
  99. return;
  100. }
  101. var resData = res.data;
  102. print(resData);
  103. if (resData['code'] == 0) {
  104. callback(resData['data']);
  105. }
  106. }
  107. @override
  108. void initState() {
  109. super.initState();
  110. diffTabCtrl = TabController(length: 3, vsync: this);
  111. sameTabCtrl = TabController(length: 2, vsync: this);
  112. listMap[1]['control'] = _scrollControllerNear;
  113. listMap[2]['control'] = _scrollControllerNew;
  114. listMap[3]['control'] = _scrollControllerApply;
  115. listMap[4]['control'] = _scrollControllerVIP;
  116. //getNewData();
  117. sameTabCtrl.addListener(() {
  118. type = sameTabCtrl.index == 0 ? 1 : 4;
  119. if (listMap[type]['list'].length == 0) getNewData();
  120. });
  121. diffTabCtrl.addListener(() {
  122. type = diffTabCtrl.index + 1;
  123. if (listMap[type]['list'].length == 0) getNewData();
  124. });
  125. MessageMgr().on('test_Permission', msgTestPermission);
  126. MessageMgr().on('refresh_love_list', msgRefreshLoveList);
  127. }
  128. msgRefreshLoveList(data) {
  129. print('msgRefreshLoveList ${data['UserId'] is String}');
  130. for (int i = 0; i < listMap[type]['list'].length; i++) {
  131. var item = listMap[type]['list'][i];
  132. print(item['UserId'] == data['UserId']);
  133. if (item['UserId'] == data['UserId']) {
  134. item['Follow'] = data['flag'];
  135. print(listMap[type]['list'][i]);
  136. break;
  137. }
  138. }
  139. setState(() {});
  140. }
  141. msgTestPermission(data) async {
  142. PermissionStatus status =
  143. await LocationPermissions().checkPermissionStatus();
  144. if (status == PermissionStatus.granted) {
  145. UserData().hasLocationPermission = true;
  146. _onRefresh();
  147. }
  148. }
  149. @override
  150. void dispose() {
  151. _scrollControllerNear.dispose();
  152. _scrollControllerNew.dispose();
  153. _scrollControllerApply.dispose();
  154. _scrollControllerVIP.dispose();
  155. sameTabCtrl.dispose();
  156. diffTabCtrl.dispose();
  157. MessageMgr().off('test_Permission', msgTestPermission);
  158. MessageMgr().off('refresh_love_list', msgRefreshLoveList);
  159. super.dispose();
  160. }
  161. var _selectTempFirstLevelIndex = '1';
  162. var _selectFirstLevelIndex = '1';
  163. var _selectSecondLevelIndex = '-1';
  164. _buildAddressWidget(void itemOnTap(String key, String value)) {
  165. List firstLevels = [
  166. {'key': '1', 'value': I18n.of(context).nearby},
  167. ];
  168. if (WebData().provinces.length > 0) {
  169. if (UserData().isInChina) {
  170. firstLevels
  171. .add({'key': 'China', 'value': WebData().provinces['China']});
  172. } else {
  173. firstLevels
  174. .add({'key': 'VietNam', 'value': WebData().provinces['VietNam']});
  175. }
  176. }
  177. List secondLevels = [];
  178. if (WebData().cities.length > 0) {
  179. if (UserData().isInChina) {
  180. WebData()
  181. .cities['China']
  182. .forEach((k, v) => secondLevels.add({'key': k, 'value': v}));
  183. } else {
  184. WebData()
  185. .cities['VietNam']
  186. .forEach((k, v) => secondLevels.add({'key': k, 'value': v}));
  187. }
  188. }
  189. Widget _buildRow(item) {
  190. var index = item['key'];
  191. return GestureDetector(
  192. onTap: () {
  193. _selectSecondLevelIndex = index;
  194. _selectFirstLevelIndex = _selectTempFirstLevelIndex;
  195. itemOnTap(index, item['value']);
  196. },
  197. child: Container(
  198. height: 50,
  199. decoration: BoxDecoration(
  200. border: Border(top: Constants.GreyBorderSide),
  201. ),
  202. alignment: Alignment.center,
  203. child: Text(
  204. item['value'],
  205. textScaleFactor: 1.0,
  206. style: TextStyle(
  207. decoration: TextDecoration.none,
  208. color: _selectFirstLevelIndex == _selectTempFirstLevelIndex &&
  209. _selectSecondLevelIndex == index
  210. ? const Color(0xFF0368FF)
  211. : Constants.BlackTextColor,
  212. fontWeight: FontWeight.normal,
  213. fontSize: 14),
  214. )),
  215. );
  216. }
  217. return Container(
  218. child: Row(
  219. children: <Widget>[
  220. Container(
  221. width: MediaQuery.of(context).size.width * 0.4,
  222. child: ListView(
  223. padding: EdgeInsets.zero,
  224. children: firstLevels.map((item) {
  225. var index = item['key'];
  226. return GestureDetector(
  227. onTap: () {
  228. _selectTempFirstLevelIndex = index;
  229. if (index == '1' || index == '2') {
  230. itemOnTap(index, item['value']);
  231. return;
  232. }
  233. setState(() {});
  234. },
  235. child: Container(
  236. height: 50,
  237. decoration: BoxDecoration(
  238. color: _selectTempFirstLevelIndex == index
  239. ? const Color(0xFF0368FF)
  240. : Colors.white,
  241. border: Border(top: Constants.GreyBorderSide),
  242. ),
  243. alignment: Alignment.center,
  244. child: Text(
  245. item['value'],
  246. textScaleFactor: 1.0,
  247. style: TextStyle(
  248. color: _selectTempFirstLevelIndex == index
  249. ? Colors.white
  250. : Constants.BlackTextColor,
  251. fontWeight: FontWeight.normal,
  252. decoration: TextDecoration.none,
  253. fontSize: 14),
  254. )));
  255. }).toList(),
  256. )),
  257. Expanded(
  258. child: Container(
  259. width: double.infinity,
  260. decoration:
  261. BoxDecoration(border: Border(left: Constants.GreyBorderSide)),
  262. child: ListView(
  263. padding: EdgeInsets.zero,
  264. children: _selectTempFirstLevelIndex == '1'
  265. ? [
  266. _buildRow({'key': '1', 'value': I18n.of(context).nearby})
  267. ]
  268. : (_selectTempFirstLevelIndex == '2'
  269. ? [
  270. _buildRow({
  271. 'key': '2',
  272. 'value': I18n.of(context).Resident_city
  273. })
  274. ]
  275. : secondLevels.map((item) {
  276. return _buildRow(item);
  277. }).toList()),
  278. ),
  279. ),
  280. )
  281. ],
  282. ));
  283. }
  284. Widget _buildAppBar() {
  285. Widget title = InkWell(
  286. highlightColor: Colors.transparent,
  287. radius: 0,
  288. onTap: UserData().isInChina
  289. ? null
  290. : () {
  291. _dropdownMenuController.dropDownHearderHeight = 70;
  292. _dropdownMenuController.show(0);
  293. },
  294. child: Container(
  295. child: Row(
  296. crossAxisAlignment: CrossAxisAlignment.center,
  297. mainAxisAlignment: MainAxisAlignment.center,
  298. children: <Widget>[
  299. Text(
  300. titleStr == '' ? I18n.of(context).nearby : titleStr,
  301. textScaleFactor: 1.0,
  302. //style: Constants.MainTitleStyle,
  303. ),
  304. UserData().isInChina
  305. ? Container()
  306. : Icon(
  307. Icons.arrow_drop_down,
  308. color: Constants.BlackTextColor,
  309. )
  310. ],
  311. )));
  312. Widget leading = Container(
  313. child: Row(
  314. children: <Widget>[
  315. CircleAvatar(
  316. backgroundColor: Colors.grey[100],
  317. radius: 13.75,
  318. child: Padding(
  319. padding: EdgeInsets.only(bottom: 1.5),
  320. child: ToggleButton(
  321. activeIcon: IconData(
  322. 0xe61e,
  323. fontFamily: 'iconfont',
  324. ),
  325. unActiveIcon: IconData(
  326. 0xe61f,
  327. fontFamily: 'iconfont',
  328. ),
  329. active: isWomen,
  330. activeColor: Constants.BlackTextColor,
  331. unActiveColor: Colors.transparent,
  332. onChange: (state) {
  333. setState(() {
  334. isWomen = !isWomen;
  335. sameTabCtrl.index = 0;
  336. diffTabCtrl.index = 0;
  337. getNewData();
  338. });
  339. },
  340. ))),
  341. SizedBox(width: 10),
  342. CustomUI.buildCircleIconButton(0xe619,
  343. onPressed: () => Navigator.of(context).push(
  344. new MaterialPageRoute(
  345. builder: (context) {
  346. return SearchPage();
  347. },
  348. ),
  349. ),
  350. padding: EdgeInsets.only(bottom: 1)),
  351. ],
  352. ),
  353. );
  354. Color borderColor =
  355. isOnline ? Constants.LightBlueButtonColor : Constants.GreyTextColor;
  356. Color textColor = isOnline ? Colors.white : Constants.GreyTextColor;
  357. Color bgColor = isOnline
  358. ? Constants.LightBlueButtonColor
  359. : Constants.LightGreyBackgroundColor;
  360. Widget actions = GestureDetector(
  361. child: Container(
  362. margin: EdgeInsets.only(right: 16, bottom: 0),
  363. alignment: Alignment.center,
  364. child: Text(
  365. I18n.of(context).first_online,
  366. textScaleFactor: 1.0,
  367. style: TextStyle(color: textColor, fontSize: 11.5),
  368. ),
  369. padding: EdgeInsets.only(left: 11, right: 11, bottom: 3, top: 2),
  370. decoration: BoxDecoration(
  371. color: bgColor,
  372. border: Border.all(color: borderColor, width: 1),
  373. borderRadius: BorderRadius.all(Radius.circular(5.0))),
  374. ),
  375. onTap: () {
  376. setState(() {
  377. isOnline = !isOnline;
  378. getNewData();
  379. });
  380. },
  381. );
  382. return AppBar(
  383. backgroundColor: Constants.LightGreyBackgroundColor,
  384. title: title,
  385. centerTitle: true,
  386. actions: <Widget>[leading],
  387. leading: CustomUI.buildCustomLeading(context),
  388. elevation: 0,
  389. bottom: PreferredSize(
  390. preferredSize:
  391. Size.fromHeight(UserData().hasLocationPermission ? 28 : 52),
  392. child: Column(
  393. children: <Widget>[
  394. Container(
  395. padding: EdgeInsets.only(left: 2),
  396. width: Screen.width,
  397. decoration: BoxDecoration(
  398. color: Constants.LightGreyBackgroundColor,
  399. border: Border(
  400. bottom: UserData().hasLocationPermission
  401. ? BorderSide(color: Color(0xffeaeaea))
  402. : BorderSide.none)),
  403. alignment: Alignment.centerLeft,
  404. child: Stack(
  405. alignment: Alignment.centerLeft,
  406. children: <Widget>[
  407. tabBar(),
  408. Positioned(right: 0, bottom: 4, child: actions)
  409. ],
  410. ),
  411. ),
  412. // !UserData().hasLocationPermission
  413. // ? InkWell(
  414. // onTap: () {
  415. // CustomUI.buildOneConfirm(
  416. // context,
  417. // I18n.of(context).get_location,
  418. // I18n.of(context).determine, () async {
  419. // Navigator.of(context).pop();
  420. // LocationPermissions().openAppSettings();
  421. // }, title: I18n.of(context).open_location);
  422. // },
  423. // child: Container(
  424. // height: 25,
  425. // alignment: Alignment.center,
  426. // width: double.infinity,
  427. // child: Row(
  428. // crossAxisAlignment: CrossAxisAlignment.center,
  429. // mainAxisAlignment: MainAxisAlignment.center,
  430. // children: <Widget>[
  431. // Text(
  432. // I18n.of(context).not_positioned,
  433. // textScaleFactor: 1,
  434. // style: TextStyle(
  435. // fontSize: 12.5,
  436. // color: const Color(0xffab8f60)),
  437. // ),
  438. // Icon(
  439. // Icons.chevron_right,
  440. // size: 18,
  441. // color: const Color(0xffab8f60),
  442. // )
  443. // ],
  444. // ),
  445. // color: const Color(0xfffaefcf),
  446. // ))
  447. // : Container()
  448. ],
  449. )),
  450. );
  451. }
  452. buildSexBar(bool isWomen) {
  453. List<Widget> feMaleTabs = [
  454. Text(I18n.of(context).nearby, textScaleFactor: 1.0),
  455. Text(I18n.of(context).new_registration, textScaleFactor: 1.0),
  456. Text(I18n.of(context).authenticate, textScaleFactor: 1.0),
  457. ];
  458. List<Widget> maleTabs = [
  459. Text(I18n.of(context).nearby, textScaleFactor: 1.0),
  460. Text(I18n.of(context).member, textScaleFactor: 1.0),
  461. ];
  462. return TabBar(
  463. isScrollable: true,
  464. indicatorPadding: EdgeInsets.only(left: 9, right: 9),
  465. tabs: isWomen ? feMaleTabs : maleTabs,
  466. controller: isWomen ? diffTabCtrl : sameTabCtrl,
  467. );
  468. }
  469. Widget tabBar() {
  470. return Container(
  471. alignment: Alignment.centerLeft,
  472. width: Screen.width,
  473. child: buildSexBar(isWomen));
  474. }
  475. @override
  476. Widget build(BuildContext context) {
  477. GZXDropDownMenu menu = GZXDropDownMenu(
  478. // controller用于控制menu的显示或隐藏
  479. controller: _dropdownMenuController,
  480. // 下拉菜单显示或隐藏动画时长
  481. animationMilliseconds: 150,
  482. // 下拉菜单,高度自定义,你想显示什么就显示什么,完全由你决定,你只需要在选择后调用_dropdownMenuController.hide();即可
  483. menus: [
  484. GZXDropdownMenuBuilder(
  485. dropDownHeight: 50 * 8.0,
  486. callback: () {
  487. setState(() {});
  488. },
  489. dropDownWidget: _buildAddressWidget((key, value) {
  490. setState(() {});
  491. isLoading = true;
  492. titleStr = value;
  493. _dropdownMenuController.hide();
  494. search = key;
  495. getNewData();
  496. })),
  497. ],
  498. );
  499. var footer = CustomUI.buildLoadingFooter();
  500. Widget diffView = TabBarView(
  501. children: <Widget>[
  502. SmartRefresher(
  503. enablePullDown: true,
  504. enablePullUp: true,
  505. header: MaterialClassicHeader(),
  506. footer: footer,
  507. controller: _scrollControllerNear,
  508. onRefresh: _onRefresh,
  509. onLoading: _onLoading,
  510. child:
  511. (_scrollControllerNear.headerStatus == RefreshStatus.completed &&
  512. listMap[1]['list'].length == 0)
  513. ? CustomUI.buildNoData(context)
  514. : ListView.builder(
  515. itemBuilder: _renderRowNear,
  516. itemCount: listMap[1]['list'].length,
  517. ),
  518. ),
  519. SmartRefresher(
  520. enablePullDown: true,
  521. enablePullUp: true,
  522. header: MaterialClassicHeader(),
  523. footer: footer,
  524. controller: _scrollControllerNew,
  525. onRefresh: _onRefresh,
  526. onLoading: _onLoading,
  527. child:
  528. (_scrollControllerNew.headerStatus == RefreshStatus.completed &&
  529. listMap[2]['list'].length == 0)
  530. ? CustomUI.buildNoData(context)
  531. : ListView.builder(
  532. itemBuilder: _renderRowNew,
  533. itemCount: listMap[2]['list'].length,
  534. ),
  535. ),
  536. SmartRefresher(
  537. enablePullDown: true,
  538. enablePullUp: true,
  539. header: MaterialClassicHeader(),
  540. footer: footer,
  541. controller: _scrollControllerApply,
  542. onRefresh: _onRefresh,
  543. onLoading: _onLoading,
  544. child:
  545. (_scrollControllerApply.headerStatus == RefreshStatus.completed &&
  546. listMap[3]['list'].length == 0)
  547. ? CustomUI.buildNoData(context)
  548. : ListView.builder(
  549. itemBuilder: _renderRowApply,
  550. itemCount: listMap[3]['list'].length,
  551. ),
  552. ),
  553. ],
  554. controller: diffTabCtrl,
  555. );
  556. Widget sampView = TabBarView(
  557. children: <Widget>[
  558. SmartRefresher(
  559. enablePullDown: true,
  560. enablePullUp: true,
  561. header: MaterialClassicHeader(),
  562. footer: footer,
  563. controller: _scrollControllerNear,
  564. onRefresh: _onRefresh,
  565. onLoading: _onLoading,
  566. child:
  567. (_scrollControllerNear.headerStatus == RefreshStatus.completed &&
  568. listMap[1]['list'].length == 0)
  569. ? CustomUI.buildNoData(context)
  570. : ListView.builder(
  571. itemBuilder: _renderRowNear,
  572. itemCount: listMap[1]['list'].length,
  573. ),
  574. ),
  575. SmartRefresher(
  576. enablePullDown: true,
  577. enablePullUp: true,
  578. header: MaterialClassicHeader(),
  579. footer: footer,
  580. controller: _scrollControllerVIP,
  581. onRefresh: _onRefresh,
  582. onLoading: _onLoading,
  583. child:
  584. (_scrollControllerVIP.headerStatus == RefreshStatus.completed &&
  585. listMap[4]['list'].length == 0)
  586. ? CustomUI.buildNoData(context)
  587. : ListView.builder(
  588. itemBuilder: _renderRowVIP,
  589. itemCount: listMap[4]['list'].length,
  590. ),
  591. ),
  592. ],
  593. controller: sameTabCtrl,
  594. );
  595. return Stack(
  596. children: <Widget>[
  597. Scaffold(
  598. appBar: _buildAppBar(),
  599. body: SafeArea(
  600. child: Stack(
  601. children: <Widget>[
  602. !isWomen ? sampView : diffView,
  603. isLoading ? CustomUI.buildLoaingAnim(context) : Container(),
  604. ],
  605. ),
  606. )),
  607. menu
  608. ],
  609. );
  610. }
  611. Widget _renderRow(int index, list, page) {
  612. if (index < list.length) {
  613. var userInfo = list[index];
  614. print('----------------------------------------------------');
  615. print(userInfo);
  616. return UserCard(
  617. key: UniqueKey(),
  618. userName: Provider.of<RefNameProvider>(context)
  619. .getRefName(userInfo['UserId'], userInfo['NickName']),
  620. city: WebData().getCountry(
  621. userInfo['Country']), //WebData().getCity(userInfo['City']),
  622. headUrl: userInfo['Headimgurl'],
  623. isReal: userInfo['IsAttestation'] == 1,
  624. constellation:
  625. WebData().getConstellation(context, userInfo['Constellation']),
  626. distance: userInfo['Distance'].toDouble(),
  627. age: userInfo['Age'],
  628. professional: WebData().getProffesionName(userInfo['Occupation']),
  629. isOnline: userInfo['OnlineStatus'] == 1
  630. ? I18n.of(context).online
  631. : WebData().getLoginTime(context, userInfo['LoginDate']),
  632. hiddenDistince: userInfo['DistanceStatus'] == 1,
  633. sex: userInfo['Sex'],
  634. isLove: userInfo['Follow'] == 0,
  635. isBalck: userInfo['Follow'] == 1,
  636. userId: userInfo['UserId'],
  637. payImg: userInfo['PhotoAut'] == 1,
  638. isHidden: userInfo['InfoAut'] == 1,
  639. member: userInfo['IsMember'],
  640. imgNum: userInfo['PhotoNum'],
  641. );
  642. }
  643. return Container();
  644. }
  645. Widget _renderRowNear(BuildContext context, int index) {
  646. return _renderRow(index, listMap[1]['list'], listMap[1]['page']);
  647. }
  648. Widget _renderRowNew(BuildContext context, int index) {
  649. return _renderRow(index, listMap[2]['list'], listMap[2]['page']);
  650. }
  651. Widget _renderRowApply(BuildContext context, int index) {
  652. return _renderRow(index, listMap[3]['list'], listMap[3]['page']);
  653. }
  654. Widget _renderRowVIP(BuildContext context, int index) {
  655. return _renderRow(index, listMap[4]['list'], listMap[4]['page']);
  656. }
  657. Future<Null> _onRefresh() async {
  658. getNewData();
  659. }
  660. }