Hibok
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

945 строки
30 KiB

  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:chat/data/UserData.dart';
  3. import 'package:chat/data/WebData.dart';
  4. import 'package:chat/data/constants.dart';
  5. import 'package:chat/generated/i18n.dart';
  6. import 'package:chat/home/AddProgram.dart';
  7. import 'package:chat/utils/CustomUI.dart';
  8. import 'package:chat/utils/HttpUtil.dart';
  9. import 'package:chat/utils/MessageBox.dart';
  10. import 'package:chat/utils/MessageMgr.dart';
  11. import 'package:chat/utils/PopUpMenu.dart' as myPop;
  12. import 'package:chat/utils/TokenMgr.dart';
  13. import 'package:chat/utils/screen.dart';
  14. import 'package:dio/dio.dart';
  15. import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'
  16. as myExt;
  17. import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
  18. import 'package:flutter/material.dart';
  19. import 'package:flutter_swiper/flutter_swiper.dart';
  20. import 'package:chat/utils/DropDownMemu.dart';
  21. import 'package:oktoast/oktoast.dart';
  22. import 'package:url_launcher/url_launcher.dart';
  23. const ChinaKey = 'China-ChinaRepeat';
  24. class SortCondition {
  25. String key;
  26. String name;
  27. bool isSelected;
  28. SortCondition({this.name, this.isSelected, this.key});
  29. }
  30. class ParkPage extends StatefulWidget {
  31. final int searchType;
  32. ParkPage({Key key, this.searchType = -1}) : super(key: key);
  33. _ParkPageState createState() => _ParkPageState();
  34. }
  35. class _ParkPageState extends State<ParkPage> {
  36. List<String> _dropDownHeaderItemStrings = [];
  37. List<SortCondition> _sexSortCondition = [];
  38. List<SortCondition> _timeSortConditions = [];
  39. SortCondition _selectSexSortCondition;
  40. SortCondition _selectTimeSortCondition;
  41. ScrollController _scrollController = new ScrollController();
  42. GlobalKey<NestedScrollViewState> _key = GlobalKey<NestedScrollViewState>();
  43. bool isLoadingFinish = false;
  44. List bannerImages = [];
  45. String timeCat = '1';
  46. String search = '1';
  47. String guid = '';
  48. bool isLoading = false; //是否正在加载数据
  49. int _page = 1;
  50. int rows = 20;
  51. bool isHomePage = true;
  52. bool isOnline = false;
  53. bool loadSuccess = false;
  54. List list = [];
  55. GlobalKey _stackKey = GlobalKey();
  56. GZXDropdownMenuController _dropdownMenuController =
  57. GZXDropdownMenuController();
  58. initValues() {
  59. if (!loadSuccess) {
  60. _dropDownHeaderItemStrings = [
  61. I18n.of(context).release_time,
  62. I18n.of(context).any_sex,
  63. UserData().isInChina
  64. ? WebData().provinces['China']
  65. : I18n.of(context).unlimited_area
  66. ];
  67. search = UserData().isInChina ? ChinaKey : '1';
  68. _sexSortCondition = [
  69. SortCondition(
  70. key: '0', name: I18n.of(context).any_sex, isSelected: true),
  71. SortCondition(
  72. key: '2', name: I18n.of(context).look_women, isSelected: false),
  73. SortCondition(
  74. key: '1', name: I18n.of(context).look_men, isSelected: false)
  75. ];
  76. _selectSexSortCondition = _sexSortCondition[0];
  77. _timeSortConditions.add(SortCondition(
  78. key: '1', name: I18n.of(context).release_time, isSelected: true));
  79. _timeSortConditions.add(SortCondition(
  80. key: '2', name: I18n.of(context).activity_time, isSelected: false));
  81. _selectTimeSortCondition = _timeSortConditions[0];
  82. loadSuccess = true;
  83. getNewData();
  84. setState(() {});
  85. }
  86. }
  87. //获取新的数据
  88. void getData(callback) async {
  89. Map data = {
  90. "userId": UserData().basicInfo.userId,
  91. "time": _selectTimeSortCondition.key,
  92. "sex": _selectSexSortCondition.key,
  93. "area": search,
  94. };
  95. data['sign'] = TokenMgr().getSign(data);
  96. data['page'] = _page;
  97. data['guid'] = guid;
  98. data['rows'] = rows;
  99. data['type'] = widget.searchType;
  100. data['online'] = isOnline ? 1 : 0;
  101. data['lng'] = UserData().longitude;
  102. data['lat'] = UserData().latitude;
  103. Response res = await HttpUtil().post('station/program/dynamic', data: data);
  104. var resData = res.data;
  105. isLoadingFinish = true;
  106. if (resData['code'] == 0) {
  107. guid = resData['data']['guid'];
  108. callback(resData['data']['list']);
  109. }
  110. }
  111. void getNewData() {
  112. _page = 1;
  113. guid = '';
  114. getData((data) {
  115. list.clear();
  116. if (data != null) {
  117. list.addAll(data);
  118. }
  119. setState(() {});
  120. });
  121. }
  122. @override
  123. void dispose() {
  124. _scrollController.dispose();
  125. MessageMgr().off('delete_program', msgListDelete);
  126. MessageMgr().off('Add_program', addProgramCallback);
  127. MessageMgr().off('love_program', msgListLove);
  128. MessageMgr().off('refresh_list', msgRefreshList);
  129. MessageMgr().off('join_program', msgJoinList);
  130. super.dispose();
  131. }
  132. //发布添加回调
  133. addProgramCallback(data) {
  134. if (list.length > 0 &&
  135. list[0]['UserId'] == UserData().basicInfo.userId &&
  136. list[0]['Type'] == 0) {
  137. list.insert(1, data);
  138. } else {
  139. list.insert(0, data);
  140. }
  141. }
  142. getBanner() async {
  143. Map data = {
  144. "userid": UserData().basicInfo.userId,
  145. };
  146. data['sign'] = TokenMgr().getSign(data);
  147. Response res = await HttpUtil().post('banner/get/list', data: data);
  148. var resData = res.data;
  149. if (resData['code'] == 0) {
  150. setState(() {
  151. bannerImages = resData['data'];
  152. });
  153. }
  154. }
  155. @override
  156. void initState() {
  157. WidgetsBinding.instance.renderView.automaticSystemUiAdjustment = false;
  158. super.initState();
  159. _scrollController.addListener(() {
  160. //print('---_scrollController offset: ${_scrollController.offset}');
  161. });
  162. getBanner();
  163. isHomePage = widget.searchType == -1;
  164. MessageMgr().on('delete_program', msgListDelete);
  165. MessageMgr().on('Add_program', addProgramCallback);
  166. MessageMgr().on('love_program', msgListLove);
  167. MessageMgr().on('refresh_list', msgRefreshList);
  168. MessageMgr().on('join_program', msgJoinList);
  169. }
  170. msgJoinList(data) {
  171. for (int i = 0; i < list.length; i++) {
  172. if (list[i]['Id'] == data) {
  173. list[i]['EnrollNum']++;
  174. list[i]['IsEnroll']++;
  175. setState(() {});
  176. break;
  177. }
  178. }
  179. }
  180. msgRefreshList(data) {
  181. _onRefresh();
  182. }
  183. msgListDelete(data) {
  184. for (int i = 0; i < list.length; i++) {
  185. if (list[i]['Id'] == data) {
  186. list.removeAt(i);
  187. setState(() {});
  188. break;
  189. }
  190. }
  191. }
  192. msgListLove(data) {
  193. print('msgListLove $data');
  194. for (int i = 0; i < list.length; i++) {
  195. if (list[i]['Id'] == data) {
  196. list[i]['FabulousNum']++;
  197. list[i]['IsFabulous']++;
  198. setState(() {});
  199. break;
  200. }
  201. }
  202. }
  203. Future _getMore() async {
  204. if (!isLoading) {
  205. setState(() {
  206. isLoading = true;
  207. });
  208. getMoreData();
  209. }
  210. }
  211. void getMoreData() {
  212. _page++;
  213. getData((data) {
  214. data == null || data.length == 0 ? _page-- : list.addAll(data);
  215. isLoading = false;
  216. setState(() {});
  217. });
  218. }
  219. void addProgram(str) async {
  220. if (str == 'program') {
  221. //自己是女性,且未认证,提示去认证
  222. if (!UserData().isMan() && !UserData().basicInfo.isAttestation) {
  223. CustomUI.buildNotTrue(context);
  224. return;
  225. }
  226. if (!UserData().isCanProgram) {
  227. showToast(I18n.of(context).stop_program);
  228. } else {
  229. Navigator.of(context).push(
  230. new MaterialPageRoute(
  231. builder: (context) {
  232. return AddProgram(
  233. isProgram: true,
  234. );
  235. },
  236. ),
  237. );
  238. }
  239. } else if (str == 'dynamic') {
  240. //自己是女性,且未认证,提示去认证
  241. if (!UserData().isMan() && !UserData().basicInfo.isAttestation) {
  242. CustomUI.buildNotTrue(context);
  243. return;
  244. }
  245. Navigator.of(context).push(
  246. new MaterialPageRoute(
  247. builder: (context) {
  248. return AddProgram(
  249. isProgram: false,
  250. );
  251. },
  252. ),
  253. );
  254. }
  255. }
  256. @override
  257. Widget build(BuildContext context) {
  258. initValues();
  259. Color btnColor = isOnline ? Constants.BlueTextColor : Colors.grey[400];
  260. Widget appBar = AppBar(
  261. //automaticallyImplyLeading: !isHomePage,
  262. title: Text(
  263. isHomePage
  264. ? I18n.of(context).radio
  265. : WebData().getProgramName(context, widget.searchType),
  266. textScaleFactor: 1.0,
  267. ),
  268. leading: CustomUI.buildCustomLeading(context),
  269. elevation: 0,
  270. actions: <Widget>[
  271. isHomePage
  272. ? myPop.PopupMenuButton<String>(
  273. padding: EdgeInsets.zero,
  274. offset: Offset(0, 45),
  275. child: new Padding(
  276. padding:
  277. EdgeInsets.only(right: 15, left: 15, top: 20, bottom: 10),
  278. child: CircleAvatar(
  279. backgroundColor: Constants.GreyBackgroundColor,
  280. radius: 13.75,
  281. child: Icon(
  282. IconData(0xe697, fontFamily: 'iconfont'),
  283. color: Constants.BlackTextColor,
  284. size: 15,
  285. )),
  286. ),
  287. onSelected: (str) {
  288. addProgram(str);
  289. },
  290. itemBuilder: (BuildContext context) =>
  291. <myPop.PopupMenuEntry<String>>[
  292. myPop.PopupMenuItem<String>(
  293. value: 'program',
  294. child: Container(
  295. margin: EdgeInsets.only(top: 15, bottom: 15),
  296. child: Text(
  297. I18n.of(context).release_program,
  298. textScaleFactor: 1.0,
  299. textAlign: TextAlign.center,
  300. ),
  301. )),
  302. myPop.PopupMenuDivider(
  303. height: 1,
  304. ),
  305. myPop.PopupMenuItem<String>(
  306. value: 'dynamic',
  307. child: Container(
  308. margin: EdgeInsets.only(top: 15, bottom: 15),
  309. child: Text(
  310. I18n.of(context).release_dynamics,
  311. textScaleFactor: 1.0,
  312. textAlign: TextAlign.center,
  313. )),
  314. ),
  315. ],
  316. )
  317. : GestureDetector(
  318. child: Container(
  319. alignment: Alignment.center,
  320. margin: EdgeInsets.only(top: 15, bottom: 10, right: 10),
  321. child: Text(I18n.of(context).first_online,
  322. textScaleFactor: 1.0,
  323. style: TextStyle(color: btnColor, fontSize: 13),
  324. textAlign: TextAlign.center),
  325. padding: EdgeInsets.only(left: 20, right: 20),
  326. decoration: BoxDecoration(
  327. border: Border.all(color: btnColor, width: 1),
  328. borderRadius: BorderRadius.all(Radius.circular(5.0))),
  329. ),
  330. onTap: () {
  331. setState(() {
  332. isOnline = !isOnline;
  333. getNewData();
  334. });
  335. },
  336. ),
  337. ],
  338. centerTitle: true,
  339. );
  340. return Scaffold(
  341. body: SafeArea(
  342. child: Center(
  343. child: Container(
  344. height: MediaQuery.of(context).size.height,
  345. width: MediaQuery.of(context).size.width,
  346. child: _buildBody(),
  347. ),
  348. )),
  349. appBar: appBar,
  350. );
  351. }
  352. Future<Null> _onRefresh() async {
  353. getNewData();
  354. }
  355. //分类按钮
  356. Widget _buildCategoryButton() {
  357. return Container(
  358. padding: EdgeInsets.only(top: 10),
  359. child: Column(
  360. children: <Widget>[
  361. Container(
  362. child: Row(
  363. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  364. children: <Widget>[
  365. _buildIconButton(1, WebData().getProgramName(context, 0),
  366. Constants.Category1Color, 0),
  367. _buildIconButton(2, WebData().getProgramName(context, 1),
  368. Constants.Category2Color, 1),
  369. _buildIconButton(3, WebData().getProgramName(context, 2),
  370. Constants.Category3Color, 2),
  371. _buildIconButton(4, WebData().getProgramName(context, 3),
  372. Constants.Category4Color, 3),
  373. ],
  374. ),
  375. ),
  376. Container(
  377. child: Row(
  378. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  379. children: <Widget>[
  380. _buildIconButton(5, WebData().getProgramName(context, 4),
  381. Constants.Category5Color, 4),
  382. _buildIconButton(6, WebData().getProgramName(context, 5),
  383. Constants.Category6Color, 5),
  384. _buildIconButton(7, WebData().getProgramName(context, 6),
  385. Constants.Category7Color, 6),
  386. _buildIconButton(8, WebData().getProgramName(context, 7),
  387. Constants.Category8Color, 7),
  388. ],
  389. ),
  390. ),
  391. ],
  392. ));
  393. }
  394. Widget _buildIconButton(iconNum, str, strColor, value) {
  395. Widget icon = Container(
  396. padding: EdgeInsets.only(left: 10, right: 10, bottom: 8),
  397. child: Image.asset(
  398. 'assets/images/park/qz_icon$iconNum.png',
  399. height: 50,
  400. ));
  401. Widget text = Positioned(
  402. bottom: 0,
  403. child: Container(
  404. child: new Text(str,
  405. textScaleFactor: 1.0,
  406. style: TextStyle(color: strColor, fontSize: 11)),
  407. ));
  408. return InkWell(
  409. onTap: () {
  410. Navigator.of(context).push(
  411. new MaterialPageRoute(
  412. builder: (context) {
  413. return ParkPage(
  414. searchType: value,
  415. );
  416. },
  417. ),
  418. );
  419. },
  420. highlightColor: Colors.transparent,
  421. radius: 0,
  422. child: Container(
  423. alignment: Alignment.center,
  424. width: (MediaQuery.of(context).size.width) / 4,
  425. margin: EdgeInsets.only(top: 10),
  426. child: Stack(
  427. alignment: Alignment.center,
  428. children: <Widget>[
  429. icon,
  430. text,
  431. ],
  432. ),
  433. ));
  434. }
  435. Widget _buildBody() {
  436. double height = Screen.width * 0.285 + 205;
  437. double headerHeight = 46;
  438. Widget header = Container(
  439. decoration: BoxDecoration(
  440. border: Border(bottom: BorderSide(color: Colors.grey[350]))),
  441. padding: EdgeInsets.only(left: 5, right: 5),
  442. child: GZXDropDownHeader(
  443. // 下拉的头部项,目前每一项,只能自定义显示的文字、图标、图标大小修改
  444. items: [
  445. GZXDropDownHeaderItem(_dropDownHeaderItemStrings[0]),
  446. GZXDropDownHeaderItem(_dropDownHeaderItemStrings[1]),
  447. GZXDropDownHeaderItem(_dropDownHeaderItemStrings[2]),
  448. ],
  449. style: TextStyle(color: Constants.BlackTextColor, fontSize: 12),
  450. height: headerHeight,
  451. // GZXDropDownHeader对应第一父级Stack的key
  452. stackKey: _stackKey,
  453. // controller用于控制menu的显示或隐藏
  454. controller: _dropdownMenuController,
  455. // 当点击头部项的事件,在这里可以进行页面跳转或openEndDrawer
  456. onItemTap: (index) {
  457. var nums = height - headerHeight;
  458. if (_scrollController.offset < nums) {
  459. _scrollController.jumpTo(nums);
  460. }
  461. },
  462. dividerHeight: 0,
  463. borderColor: Colors.white,
  464. borderWidth: 0,
  465. dropDownStyle:
  466. TextStyle(color: const Color(0xFF0368FF), fontSize: 12),
  467. ));
  468. GZXDropDownMenu menu = GZXDropDownMenu(
  469. // controller用于控制menu的显示或隐藏
  470. controller: _dropdownMenuController,
  471. // 下拉菜单显示或隐藏动画时长
  472. animationMilliseconds: 150,
  473. // 下拉菜单,高度自定义,你想显示什么就显示什么,完全由你决定,你只需要在选择后调用_dropdownMenuController.hide();即可
  474. menus: [
  475. GZXDropdownMenuBuilder(
  476. dropDownHeight: 50.0 * _timeSortConditions.length,
  477. callback: () {
  478. setState(() {});
  479. },
  480. dropDownWidget:
  481. _buildConditionListWidget(_timeSortConditions, (value) {
  482. _selectTimeSortCondition = value;
  483. _dropDownHeaderItemStrings[0] = _selectTimeSortCondition.name;
  484. _dropdownMenuController.hide();
  485. isLoadingFinish = false;
  486. getNewData();
  487. setState(() {});
  488. })),
  489. GZXDropdownMenuBuilder(
  490. dropDownHeight: 50.0 * _sexSortCondition.length,
  491. callback: () {
  492. setState(() {});
  493. },
  494. dropDownWidget:
  495. _buildConditionListWidget(_sexSortCondition, (value) {
  496. _selectSexSortCondition = value;
  497. _dropDownHeaderItemStrings[1] = _selectSexSortCondition.name;
  498. _dropdownMenuController.hide();
  499. isLoadingFinish = false;
  500. getNewData();
  501. setState(() {});
  502. })),
  503. GZXDropdownMenuBuilder(
  504. dropDownHeight: 50 * 8.0,
  505. callback: () {
  506. setState(() {});
  507. },
  508. dropDownWidget: _buildAddressWidget((key, value) {
  509. search = key;
  510. _dropDownHeaderItemStrings[2] = value;
  511. _dropdownMenuController.hide();
  512. isLoadingFinish = false;
  513. getNewData();
  514. setState(() {});
  515. })),
  516. ],
  517. );
  518. var v = Column(
  519. children: <Widget>[
  520. _buildSwiperImageWidget(),
  521. _buildCategoryButton(),
  522. ],
  523. );
  524. var body = myExt.NestedScrollView(
  525. key: _key,
  526. controller: _scrollController,
  527. pinnedHeaderSliverHeightBuilder: () {
  528. return headerHeight;
  529. },
  530. innerScrollPositionKeyBuilder: () {
  531. var index = "Tab";
  532. // index += primaryTC.index.toString();
  533. return Key(index);
  534. },
  535. headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
  536. return <Widget>[
  537. SliverAppBar(
  538. pinned: true,
  539. automaticallyImplyLeading: false,
  540. floating: true,
  541. elevation: 0,
  542. snap: false,
  543. forceElevated: boxIsScrolled,
  544. flexibleSpace: FlexibleSpaceBar(
  545. collapseMode: CollapseMode.pin,
  546. background: Column(
  547. crossAxisAlignment: CrossAxisAlignment.start,
  548. children: <Widget>[v],
  549. ),
  550. ),
  551. expandedHeight: (Screen.width * 0.285 + 205),
  552. bottom: PreferredSize(
  553. preferredSize: Size(double.infinity, headerHeight + 1),
  554. child: Stack(
  555. key: _stackKey,
  556. children: <Widget>[
  557. header,
  558. ],
  559. ),
  560. ),
  561. )
  562. ];
  563. },
  564. body: Center(
  565. child: Container(
  566. color: Constants.GreyBackgroundColor,
  567. child: NotificationListener<ScrollNotification>(
  568. onNotification: (scrollNotification) {
  569. final maxScroll = scrollNotification.metrics.maxScrollExtent;
  570. final currentScroll = scrollNotification.metrics.pixels;
  571. if (maxScroll == currentScroll) {
  572. _getMore();
  573. }
  574. return;
  575. },
  576. child: ListView.builder(
  577. physics: ClampingScrollPhysics(),
  578. itemBuilder: _renderRowNear,
  579. itemCount: list.length + 1,
  580. ),
  581. )),
  582. ),
  583. );
  584. var newBody = myExt.NestedScrollViewRefreshIndicator(
  585. onRefresh: _onRefresh,
  586. child: body,
  587. );
  588. var body1 = Stack(
  589. key: _stackKey,
  590. children: <Widget>[
  591. Container(
  592. margin: EdgeInsets.only(top: headerHeight),
  593. child: RefreshIndicator(
  594. onRefresh: _onRefresh,
  595. child: NotificationListener<ScrollNotification>(
  596. onNotification: (scrollNotification) {
  597. final maxScroll = scrollNotification.metrics.maxScrollExtent;
  598. final currentScroll = scrollNotification.metrics.pixels;
  599. if (maxScroll == currentScroll) {
  600. _getMore();
  601. }
  602. return;
  603. },
  604. child: ListView.builder(
  605. itemBuilder: _renderRowNear,
  606. itemCount: list.length + 1,
  607. ),
  608. ),
  609. )),
  610. Container(
  611. decoration: BoxDecoration(
  612. border: Border(bottom: BorderSide(color: Colors.grey[300])),
  613. color: Colors.white,
  614. ),
  615. child: header,
  616. ),
  617. ],
  618. );
  619. return Stack(
  620. children: <Widget>[
  621. isHomePage ? newBody : body1,
  622. menu,
  623. isLoadingFinish ? Container() : CustomUI.buildLoaingAnim(context)
  624. ],
  625. );
  626. }
  627. Widget _renderRowNear(BuildContext context, int index) {
  628. if ((list == null || list.length == 0) && isLoadingFinish) {
  629. return CustomUI.buildNoData(context);
  630. //return CustomUI.buildNoData(context);
  631. }
  632. if (index < list.length) {
  633. var userInfo = list[index];
  634. return MessageBox(programInfo: userInfo);
  635. }
  636. if (list.length > rows * _page) return _getMoreWidget();
  637. return Container();
  638. }
  639. Widget _getMoreWidget() {
  640. return Center(
  641. child: Padding(
  642. padding: EdgeInsets.all(10.0),
  643. child: Row(
  644. mainAxisAlignment: MainAxisAlignment.center,
  645. crossAxisAlignment: CrossAxisAlignment.center,
  646. children: <Widget>[
  647. Text(
  648. '',
  649. style: TextStyle(fontSize: 16.0),
  650. ),
  651. CircularProgressIndicator(
  652. strokeWidth: 1.0,
  653. valueColor: AlwaysStoppedAnimation(Constants.BlueTextColor))
  654. ],
  655. ),
  656. ),
  657. );
  658. }
  659. //轮播图
  660. Widget _buildSwiperImageWidget() {
  661. double width = MediaQuery.of(context).size.width * 0.95;
  662. return Container(
  663. height: width * 0.3,
  664. width: width,
  665. decoration: BoxDecoration(
  666. borderRadius: BorderRadius.circular(50.0),
  667. ),
  668. child: (bannerImages == null || bannerImages.length == 0)
  669. ? Container()
  670. : Swiper(
  671. // 初始的时候下标位置
  672. index: 0,
  673. /// 无限轮播模式开关
  674. loop: true,
  675. itemBuilder: (context, index) {
  676. return GestureDetector(
  677. onTap: () async {
  678. var url = bannerImages[index]['Url'];
  679. if (await canLaunch(url)) {
  680. await launch(url);
  681. } else {
  682. throw 'Could not launch $url';
  683. }
  684. },
  685. child: Container(
  686. child: ClipPath(
  687. child: Stack(children: <Widget>[
  688. Container(
  689. width: double.infinity,
  690. child: ClipRRect(
  691. borderRadius: BorderRadius.circular(10.0),
  692. child: CachedNetworkImage(
  693. fadeOutDuration: const Duration(milliseconds: 300),
  694. fadeInDuration: const Duration(milliseconds: 700),
  695. fit: BoxFit.fill,
  696. imageUrl: bannerImages[index]['ImgUrl'],
  697. placeholder: CustomUI.buildImgLoding,
  698. errorWidget: (context, url, error) =>
  699. new Icon(Icons.error),
  700. ),
  701. ),
  702. ),
  703. ]),
  704. )),
  705. );
  706. },
  707. itemCount: bannerImages.length,
  708. /// 设置 new SwiperPagination() 展示默认分页指示器
  709. pagination: SwiperPagination(alignment: Alignment.bottomRight),
  710. /// 设置 new SwiperControl() 展示默认分页按钮
  711. // control: SwiperControl(),
  712. /// 自动播放开关.
  713. autoplay: true,
  714. /// 动画时间,单位是毫秒
  715. duration: 300,
  716. /// 当用户点击某个轮播的时候调用
  717. onTap: (index) {},
  718. /// 滚动方向,设置为Axis.vertical如果需要垂直滚动
  719. scrollDirection: Axis.horizontal,
  720. ),
  721. );
  722. }
  723. var _selectTempFirstLevelIndex = '1';
  724. var _selectFirstLevelIndex = '1';
  725. var _selectSecondLevelIndex = '-1';
  726. _buildAddressWidget(void itemOnTap(String key, String value)) {
  727. List firstLevels = [];
  728. if (WebData().provinces.length > 0) {
  729. if (UserData().isInChina) {
  730. firstLevels
  731. .add({'key': 'China', 'value': WebData().provinces['China']});
  732. } else {
  733. firstLevels
  734. .add({'key': 'VietNam', 'value': WebData().provinces['VietNam']});
  735. }
  736. }
  737. List secondLevels = [];
  738. if (WebData().cities.length > 0) {
  739. if (UserData().isInChina) {
  740. secondLevels.add(
  741. {'key': ChinaKey, 'value': WebData().provinces['China']});
  742. } else {
  743. secondLevels
  744. .add({'key': '1', 'value': I18n.of(context).unlimited_area});
  745. WebData()
  746. .cities['VietNam']
  747. .forEach((k, v) => secondLevels.add({'key': 'VietNam-$k', 'value': v}));
  748. }
  749. }
  750. _selectTempFirstLevelIndex = firstLevels[0]['key'];
  751. _selectFirstLevelIndex = firstLevels[0]['key'];
  752. _selectSecondLevelIndex = secondLevels[0]['key'];
  753. Widget buildRow(item) {
  754. var index = item['key'];
  755. return GestureDetector(
  756. onTap: () {
  757. _selectSecondLevelIndex = index;
  758. _selectFirstLevelIndex = _selectTempFirstLevelIndex;
  759. itemOnTap(index, item['value']);
  760. },
  761. child: Container(
  762. height: 50,
  763. decoration: BoxDecoration(
  764. border: Border(top: Constants.GreyBorderSide),
  765. ),
  766. alignment: Alignment.center,
  767. child: Text(
  768. item['value'],
  769. textScaleFactor: 1.0,
  770. style: TextStyle(
  771. color: _selectFirstLevelIndex == _selectTempFirstLevelIndex &&
  772. _selectSecondLevelIndex == index
  773. ? const Color(0xFF0368FF)
  774. : Constants.BlackTextColor,
  775. ),
  776. )),
  777. );
  778. }
  779. return Container(
  780. child: Row(
  781. children: <Widget>[
  782. Container(
  783. width: MediaQuery.of(context).size.width * 0.4,
  784. child: ListView(
  785. children: firstLevels.map((item) {
  786. var index = item['key'];
  787. return GestureDetector(
  788. onTap: () {
  789. _selectTempFirstLevelIndex = index;
  790. if (index == 'China') {
  791. itemOnTap(ChinaKey, item['value']);
  792. return;
  793. }
  794. setState(() {});
  795. },
  796. child: Container(
  797. height: 50,
  798. decoration: BoxDecoration(
  799. color: _selectTempFirstLevelIndex == index
  800. ? const Color(0xFF0368FF)
  801. : Colors.white,
  802. border: Border(top: Constants.GreyBorderSide),
  803. ),
  804. alignment: Alignment.center,
  805. child: Text(
  806. item['value'],
  807. textScaleFactor: 1.0,
  808. style: TextStyle(
  809. color: _selectTempFirstLevelIndex == index
  810. ? Colors.white
  811. : Constants.BlackTextColor,
  812. ),
  813. )));
  814. }).toList(),
  815. ),
  816. ),
  817. Expanded(
  818. child: Container(
  819. width: double.infinity,
  820. decoration:
  821. BoxDecoration(border: Border(left: Constants.GreyBorderSide)),
  822. child: ListView(
  823. children: secondLevels.map((item) {
  824. return buildRow(item);
  825. }).toList(),
  826. ),
  827. ),
  828. )
  829. ],
  830. ));
  831. }
  832. _buildConditionListWidget(items, void itemOnTap(sortCondition)) {
  833. return ListView.separated(
  834. shrinkWrap: true,
  835. scrollDirection: Axis.vertical,
  836. physics: const NeverScrollableScrollPhysics(),
  837. itemCount: items.length,
  838. // item 的个数
  839. separatorBuilder: (BuildContext context, int index) =>
  840. Divider(height: 1.0),
  841. // 添加分割线
  842. itemBuilder: (BuildContext context, int index) {
  843. SortCondition goodsSortCondition = items[index];
  844. return InkWell(
  845. onTap: () {
  846. for (var value in items) {
  847. value.isSelected = false;
  848. }
  849. goodsSortCondition.isSelected = true;
  850. itemOnTap(goodsSortCondition);
  851. },
  852. child: Container(
  853. height: 50,
  854. width: double.infinity,
  855. alignment: Alignment.center,
  856. child: Text(
  857. goodsSortCondition.name,
  858. textScaleFactor: 1.0,
  859. style: TextStyle(
  860. color: goodsSortCondition.isSelected
  861. ? const Color(0xFF0368FF)
  862. : Constants.BlackTextColor,
  863. ),
  864. )),
  865. );
  866. },
  867. );
  868. }
  869. }