address_selecter.dart 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import 'dart:convert';
  2. import 'dart:ui' as ui show window;
  3. import 'package:flutter/cupertino.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:flutter/services.dart';
  6. import 'package:twong/utils/index.dart';
  7. class AddressSelecter extends StatefulWidget {
  8. final String title;
  9. final Function(String province, String city, String county, int code) onSelected;
  10. final Color unselectedColor;
  11. final Color selectedColor;
  12. final double itemTextFontSize;
  13. final TextStyle titleTextStyle;
  14. AddressSelecter(
  15. {Key key,
  16. @required this.onSelected,
  17. this.title,
  18. this.unselectedColor: Colors.grey,
  19. this.selectedColor: Colors.blue,
  20. this.itemTextFontSize: 14.0,
  21. this.titleTextStyle: const TextStyle(
  22. fontSize: 16.0, color: Colors.black, fontWeight: FontWeight.bold)})
  23. : super(key: key);
  24. @override
  25. createState() => _AddressSelecterState();
  26. }
  27. class _AddressSelecterState extends State<AddressSelecter>
  28. with TickerProviderStateMixin {
  29. int _index = 0;
  30. TabController _tabController;
  31. ScrollController _controller;
  32. /// TabBar不能动态加载,所以初始化3个,其中两个文字置空,点击事件拦截住。
  33. List<Tab> myTabs = <Tab>[Tab(text: '请选择'), Tab(text: ''), Tab(text: '')];
  34. List provinces = [];
  35. List cities = [];
  36. List counties = [];
  37. /// 当前列表数据
  38. List mList = [];
  39. /// 三级联动选择的position
  40. var _positions = [0, 0, 0];
  41. double itemHeight = 48.0;
  42. @override
  43. void initState() {
  44. super.initState();
  45. _controller = ScrollController();
  46. _tabController = TabController(vsync: this, length: myTabs.length);
  47. _initData();
  48. }
  49. @override
  50. void dispose() {
  51. _tabController?.dispose();
  52. _controller?.dispose();
  53. super.dispose();
  54. }
  55. @override
  56. Widget build(BuildContext context) {
  57. return Material(
  58. color: Colors.white,
  59. child: SafeArea(
  60. child: Container(
  61. height:
  62. MediaQueryData.fromWindow(ui.window).size.height * 9.0 / 16.0,
  63. child: Column(children: <Widget>[
  64. Stack(children: <Widget>[
  65. Container(
  66. width: double.infinity,
  67. alignment: Alignment.center,
  68. padding: const EdgeInsets.symmetric(vertical: 16.0),
  69. child:
  70. Text("${widget.title}", style: widget.titleTextStyle)),
  71. Positioned(
  72. right: 0,
  73. child: IconButton(
  74. icon: Icon(Icons.close, size: 22),
  75. onPressed: () => Navigator.maybePop(context)))
  76. ]),
  77. _line,
  78. Container(
  79. color: Colors.white,
  80. alignment: Alignment.centerLeft,
  81. child: TabBar(
  82. controller: _tabController,
  83. isScrollable: true,
  84. onTap: (index) {
  85. if (myTabs[index].text.isEmpty) {
  86. _tabController.animateTo(_index);
  87. return;
  88. }
  89. switch (index) {
  90. case 0:
  91. mList = provinces;
  92. break;
  93. case 1:
  94. mList =
  95. cities = provinces[_positions[0]]['c'];
  96. break;
  97. case 2:
  98. mList =
  99. counties = cities[_positions[1]]['c'];
  100. break;
  101. }
  102. setState(() {
  103. _index = index;
  104. _controller.animateTo(_positions[_index] * itemHeight,
  105. duration: Duration(milliseconds: 10),
  106. curve: Curves.ease);
  107. });
  108. },
  109. indicatorSize: TabBarIndicatorSize.label,
  110. unselectedLabelColor: Colors.black,
  111. labelColor: widget.selectedColor,
  112. tabs: myTabs)),
  113. _line,
  114. Expanded(
  115. child: provinces.length > 0
  116. ? _buildListView()
  117. : CupertinoActivityIndicator(animating: false))
  118. ])),
  119. ));
  120. }
  121. void _initData() async {
  122. // rootBundle.loadString('assets/area.json').then((value) {
  123. // provinces = json.decode(value);
  124. // setState(() => mList = provinces);
  125. // });
  126. var data = Cache.loadString(SaveKey.areas);
  127. if(data == null) {
  128. Request.get("city_list").then((res) {
  129. provinces = res;
  130. Cache.saveString(SaveKey.areas, json.encode(res));
  131. setState(() {
  132. mList = provinces;
  133. });
  134. });
  135. Log.d("load area from network");
  136. } else {
  137. provinces = json.decode(data);
  138. setState(() {
  139. mList = provinces;
  140. });
  141. Log.d("load area from cache");
  142. }
  143. setState(() {});
  144. }
  145. Widget _buildListView() {
  146. return ListView.builder(
  147. controller: _controller,
  148. itemBuilder: (context, index) => InkWell(
  149. child: Container(
  150. padding: EdgeInsets.symmetric(horizontal: 16.0),
  151. height: itemHeight,
  152. alignment: Alignment.centerLeft,
  153. child: Row(children: <Widget>[
  154. Text(mList[index]["n"],
  155. style: TextStyle(
  156. fontSize: widget.itemTextFontSize,
  157. color: mList[index]["n"] == myTabs[_index].text
  158. ? widget.selectedColor
  159. : widget.unselectedColor)),
  160. SizedBox(height: 8),
  161. Offstage(
  162. offstage: mList[index]["n"] != myTabs[_index].text,
  163. child: Icon(Icons.check,
  164. size: 16.0, color: widget.selectedColor))
  165. ])),
  166. onTap: () {
  167. myTabs[_index] = Tab(text: mList[index]["n"]);
  168. _positions[_index] = index;
  169. _index++;
  170. switch (_index) {
  171. case 1:
  172. mList = cities = provinces[_positions[0]]['c'];
  173. myTabs[1] = Tab(text: "请选择");
  174. myTabs[2] = Tab(text: "");
  175. break;
  176. case 2:
  177. mList = counties = cities[_positions[1]]['c'];
  178. myTabs[2] = Tab(text: "请选择");
  179. break;
  180. case 3:
  181. _index = 2;
  182. widget.onSelected(
  183. provinces[_positions[0]]["n"],
  184. cities[_positions[1]]["n"],
  185. counties[_positions[2]]["n"],
  186. counties[_positions[2]]["v"]);
  187. Navigator.maybePop(context);
  188. break;
  189. }
  190. setState(() {});
  191. _controller.animateTo(0.0,
  192. duration: Duration(milliseconds: 100), curve: Curves.ease);
  193. _tabController.animateTo(_index);
  194. }),
  195. itemCount: mList.length);
  196. }
  197. Widget _line = Container(height: 0.6, color: Color(0xFFEEEEEE));
  198. }