import 'package:atui/jade/bean/PCADataBean.dart';
import 'package:atui/jade/utils/JadeColors.dart';
import 'package:atui/main.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
/*
* 传入城市数据源的省市区选择器
* 待扩展:把传入的对象类型数据源优化传入json数据,
* 并在项目中存放本地的城市json数据,当传入数据源为空时读取本地json
* */
typedef ResultBlock = void Function(CityResult result);
class CityPickerView extends StatefulWidget {
final List<PcaDataBean> params;
// 结果返回
final ResultBlock onResult;
CityPickerView({required this.onResult, required this.params});
_CityPickerViewState createState() => _CityPickerViewState();
}
class _CityPickerViewState extends State<CityPickerView> {
List<PcaDataBean> _cpaDatas = [];
int? provinceIndex;
int? cityIndex;
int? areaIndex;
late FixedExtentScrollController _provinceScrollController;
late FixedExtentScrollController _cityScrollController;
late FixedExtentScrollController _areaScrollController;
CityResult result = CityResult();
bool isShow = false;
List get provinces {
if (_cpaDatas.length > 0) {
if (provinceIndex == null) {
provinceIndex = 0;
result.province = provinces[provinceIndex!].name;
}
return _cpaDatas;
}
return [];
}
List get citys {
if (provinces.length > 0) {
return provinces[provinceIndex!].cityVOList ?? [];
}
return [];
}
List get areas {
if (citys.length > 0) {
if (cityIndex == null) {
cityIndex = 0;
result.city = citys[cityIndex!].name;
}
List list = citys[cityIndex!].districtVOList ?? [];
if (list.length > 0) {
if (areaIndex == null) {
areaIndex = 0;
result.area = list[areaIndex!].name;
}
}
return list;
}
return [];
}
// 保存选择结果
_saveInfoData() {
var prs = provinces;
var cts = citys;
var ars = areas;
if (provinceIndex != null && prs.length > 0) {
result.province = prs[provinceIndex!].name;
} else {
result.province = '';
}
if (cityIndex != null && cts.length > 0) {
result.city = cts[cityIndex!].name;
} else {
result.city = '';
}
if (areaIndex != null && ars.length > 0) {
result.area = ars[areaIndex!].name;
} else {
result.area = '';
}
}
void dispose() {
_provinceScrollController.dispose();
_cityScrollController.dispose();
_areaScrollController.dispose();
super.dispose();
}
void initState() {
super.initState();
//初始化控制器
_provinceScrollController = FixedExtentScrollController();
_cityScrollController = FixedExtentScrollController();
_areaScrollController = FixedExtentScrollController();
if (widget.params == null) {
//读取city.json数据
_loadCitys().then((value) {
setState(() {
isShow = true;
});
});
} else {
_cpaDatas = widget.params;
setState(() {
isShow = true;
});
}
}
Future _loadCitys() async {
// var cityStr = await rootBundle.loadString('assets/city.json');
// _cpaDatas = json.decode(cityStr) as List;
//result默认取第一组值
return Future.value(true);
}
Widget build(BuildContext context) {
return Material(
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_firstView(),
_contentView(),
],
),
),
);
}
Widget _firstView() {
return Container(
height: 44,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
TextButton(
child: Text('取消',style: TextStyle(
color: JadeColors.grey)),
onPressed: () {
Navigator.pop(context);
},
),
TextButton(
child: Text('确定'),
onPressed: () {
widget.onResult(result);
Navigator.pop(context);
},
),
]),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.grey.withOpacity(0.1), width: 1)),
),
);
}
Widget _contentView() {
return Container(
// color: Colors.orange,
height: 200,
child: isShow
? Row(
children: <Widget>[
Expanded(child: _provincePickerView()),
Expanded(child: _cityPickerView()),
Expanded(child: _areaPickerView()),
],
)
: Center(
child: CupertinoActivityIndicator(
animating: true,
),
),
);
}
Widget _provincePickerView() {
return Container(
child: CupertinoPicker(
scrollController: _provinceScrollController,
children: provinces.map((item) {
return Center(
child: Text(
item.name,
style: TextStyle(color: Colors.black87, fontSize: 16),
maxLines: 1,
),
);
}).toList(),
onSelectedItemChanged: (index) {
provinceIndex = index;
if (cityIndex != null) {
cityIndex = 0;
if (_cityScrollController.positions.length > 0) {
_cityScrollController.jumpTo(0);
}
}
if (areaIndex != null) {
areaIndex = 0;
if (_areaScrollController.positions.length > 0) {
_areaScrollController.jumpTo(0);
}
}
_saveInfoData();
setState(() {});
},
itemExtent: 36,
),
);
}
Widget _cityPickerView() {
return Container(
child: citys.length == 0
? Container()
: CupertinoPicker(
scrollController: _cityScrollController,
children: citys.map((item) {
return Center(
child: Text(
item.name,
style: TextStyle(color: Colors.black87, fontSize: 16),
maxLines: 1,
),
);
}).toList(),
onSelectedItemChanged: (index) {
cityIndex = index;
if (areaIndex != null) {
areaIndex = 0;
if (_areaScrollController.positions.length > 0) {
_areaScrollController.jumpTo(0);
}
}
_saveInfoData();
setState(() {});
},
itemExtent: 36,
),
);
}
Widget _areaPickerView() {
return Container(
width: double.infinity,
child: areas.length == 0
? Container()
: CupertinoPicker(
scrollController: _areaScrollController,
children: areas.map((item) {
return Center(
child: Text(
item.name,
style: TextStyle(color: Colors.black87, fontSize: 16),
maxLines: 1,
),
);
}).toList(),
onSelectedItemChanged: (index) {
areaIndex = index;
_saveInfoData();
setState(() {});
},
itemExtent: 36,
),
);
}
}
class CityResult {
/// 省市区
String? province = '';
String? city = '';
String? area = '';
CityResult({
this.province,
this.city,
this.area,
});
CityResult.fromJson(Map<String, dynamic> json) {
province = json['province'];
city = json['city'];
area = json['area'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> datas = new Map<String, dynamic>();
datas['province'] = this.province;
datas['city'] = this.city;
datas['area'] = this.area;
return datas;
}
}
class CustomCityPicker {
static cityPicker(BuildContext? context,provinceList,{required ResultBlock onResult}){
showModalBottomSheet(
context: context ?? navigatorKey.currentContext!,
isScrollControlled: true,
builder: (ctx) {
return CityPickerView(
params: provinceList,
onResult: (res) {
onResult(res);
}
);
},
);
}
}
省市区接口数据源实体类
/// name : "安徽省"
/// cityVOList : [{"name":"安庆市","districtVOList":[{"name":"大观区"},{"name":"怀宁县"},{"name":"潜山市"},{"name":"宿松县"},{"name":"桐城市"},{"name":"太湖县"},{"name":"望江县"},{"name":"迎江区"},{"name":"宜秀区"},{"name":"岳西县"}]},{"name":"蚌埠市","districtVOList":[{"name":"蚌山区"},{"name":"固镇县"},{"name":"淮上区"},{"name":"怀远县"},{"name":"龙子湖区"},{"name":"五河县"},{"name":"禹会区"}]},{"name":"亳州市","districtVOList":[{"name":"利辛县"},{"name":"蒙城县"},{"name":"谯城区"},{"name":"涡阳县"}]},{"name":"滁州市","districtVOList":[{"name":"定远县"},{"name":"凤阳县"},{"name":"来安县"},{"name":"琅琊区"},{"name":"明光市"},{"name":"南谯区"},{"name":"全椒县"},{"name":"天长市"}]},{"name":"池州市","districtVOList":[{"name":"东至县"},{"name":"贵池区"},{"name":"青阳县"},{"name":"石台县"}]},{"name":"阜阳市","districtVOList":[{"name":"阜南县"},{"name":"界首市"},{"name":"临泉县"},{"name":"太和县"},{"name":"颍东区"},{"name":"颍泉区"},{"name":"颍上县"},{"name":"颍州区"}]},{"name":"淮北市","districtVOList":[{"name":"杜集区"},{"name":"烈山区"},{"name":"濉溪县"},{"name":"相山区"}]},{"name":"合肥市","districtVOList":[{"name":"包河区"},{"name":"巢湖市"},{"name":"肥东县"},{"name":"肥西县"},{"name":"庐江县"},{"name":"庐阳区"},{"name":"蜀山区"},{"name":"瑶海区"},{"name":"长丰县"}]},{"name":"淮南市","districtVOList":[{"name":"八公山区"},{"name":"大通区"},{"name":"凤台县"},{"name":"潘集区"},{"name":"寿县"},{"name":"田家庵区"},{"name":"谢家集区"}]},{"name":"黄山市","districtVOList":[{"name":"黄山区"},{"name":"徽州区"},{"name":"祁门县"},{"name":"歙县"},{"name":"屯溪区"},{"name":"休宁县"},{"name":"黟县"}]},{"name":"六安市","districtVOList":[{"name":"霍邱县"},{"name":"霍山县"},{"name":"金安区"},{"name":"金寨县"},{"name":"舒城县"},{"name":"裕安区"},{"name":"叶集区"}]},{"name":"马鞍山市","districtVOList":[{"name":"博望区"},{"name":"当涂县"},{"name":"花山区"},{"name":"含山县"},{"name":"和县"},{"name":"雨山区"}]},{"name":"宿州市","districtVOList":[{"name":"砀山县"},{"name":"灵璧县"},{"name":"泗县"},{"name":"萧县"},{"name":"埇桥区"}]},{"name":"铜陵市","districtVOList":[{"name":"郊区"},{"name":"铜官区"},{"name":"义安区"},{"name":"枞阳县"}]},{"name":"芜湖市","districtVOList":[{"name":"繁昌区"},{"name":"镜湖区"},{"name":"鸠江区"},{"name":"南陵县"},{"name":"无为市"},{"name":"湾沚区"},{"name":"弋江区"}]},{"name":"宣城市","districtVOList":[{"name":"广德市"},{"name":"旌德县"},{"name":"泾县"},{"name":"绩溪县"},{"name":"郎溪县"},{"name":"宁国市"},{"name":"宣州区"}]}]
class PcaDataBean {
String? name;
List<CityVoList>? cityVOList;
PcaDataBean({
this.name,
this.cityVOList,});
PcaDataBean.fromJson(dynamic json) {
name = json['name'];
if (json['cityVOList'] != null) {
cityVOList = [];
json['cityVOList'].forEach((v) {
cityVOList?.add(CityVoList.fromJson(v));
});
}
}
PcaDataBean copyWith({ String? name,
List<CityVoList>? cityVOList,
}) => PcaDataBean( name: name ?? this.name,
cityVOList: cityVOList ?? this.cityVOList,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['name'] = name;
if (cityVOList != null) {
map['cityVOList'] = cityVOList?.map((v) => v.toJson()).toList();
}
return map;
}
}
/// name : "安庆市"
/// districtVOList : [{"name":"大观区"},{"name":"怀宁县"},{"name":"潜山市"},{"name":"宿松县"},{"name":"桐城市"},{"name":"太湖县"},{"name":"望江县"},{"name":"迎江区"},{"name":"宜秀区"},{"name":"岳西县"}]
class CityVoList {
String? name;
List<DistrictVoList>? districtVOList;
CityVoList({
this.name,
this.districtVOList,});
CityVoList.fromJson(dynamic json) {
name = json['name'];
if (json['districtVOList'] != null) {
districtVOList = [];
json['districtVOList'].forEach((v) {
districtVOList?.add(DistrictVoList.fromJson(v));
});
}
}
CityVoList copyWith({ String? name,
List<DistrictVoList>? districtVOList,
}) => CityVoList( name: name ?? this.name,
districtVOList: districtVOList ?? this.districtVOList,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['name'] = name;
if (districtVOList != null) {
map['districtVOList'] = districtVOList?.map((v) => v.toJson()).toList();
}
return map;
}
}
/// name : "大观区"
class DistrictVoList {
DistrictVoList({
this.name,});
DistrictVoList.fromJson(dynamic json) {
name = json['name'];
}
String? name;
DistrictVoList copyWith({ String? name,
}) => DistrictVoList( name: name ?? this.name,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['name'] = name;
return map;
}
}
调用
_showCityPicker(){
CustomCityPicker.cityPicker(context, _provinceVOList,
onResult: (result) {
setState(() {
_provinceName = result.province;
_cityName = result.city;
_districtName = result.area;
_showFullDistrict = '${result.province}${result.city}${result.area}';
});
});
}