Flutter自定义省市区选择控件及第三方city_pickers解析

Flutter自定义省市区选择控件及第三方city_pickers解析

第三方city_pickers解析

根据公司现有数据结构自定义省市区选择控件

相关自已定源码

一.项目中使用的city_pickers版本0.2.0,
pub地址:https://pub.dev/packages/city_pickers
github地址:https://github.com/hanxu317317/city_pickers
使用介绍上面的地址介绍的都非常详细,此处仅对数据源做详细解析。
若新项目,码表没有定义,推荐使用此第三方,可根据具体使用场景对数据做部分调整。
city_pickers可外部传入省字典,市区县字典数据源,格式需要符合其现有结构。
city_pickers外部没有传入数据情况下,会默认按照第三方现有数据源进行初始化,详细数据源文件在flutter pub get目录
flutter/.pub-cache/hosted/pub.flutter-io.cn/city_pickers-0.2.0/lib/meta/province.dart中。
结构见下图,所以此处如果是根据公司现有码表接口返回数据的话,要做对应转换。

在这里插入图片描述1.可见省份map是key为code,value为省份名称的结构,且包含台湾,香港,澳门,如业务中不需要可进行注释删减或根据自己公司码表按照此结构动态传入
2.citiesData为市及区县map,可根据省级code,如北京市110000查询其下属市,结果为map集合"110000": {“110100”: {“name”: “北京城区”, “alpha”: “b”}},
根据市级code,北京市110100查询其下属区县,结果为map集合包含110101,东城区,110102,西城区等
3.此数据源省code与市code确保唯一性,市code与区限code确保唯一性,所以该第三方构建以省为根结点的树结构,并根据该结构进行查找,如根据区县code查询其具体省市区县名称用于反显,详情可读源码文件在flutter pub get目录
flutter/.pub-cache/hosted/pub.flutter-io.cn/city_pickers-0.2.0/lib/modal/base_citys.dart中。
4.由于公司码表与第三方有出入,省份少一些,区县范围不一致,且存在市code与区县code相同的情况,所以最后选择了放弃,使用自定义。下面以甘肃省嘉峪关市为例,具体对比差异。
在这里插入图片描述此为第三方数据源,可见嘉峪关市code620200与其下属区县code无重复。
在这里插入图片描述
此图为公司数据源,可见城市code620200嘉峪关市,与其下属区县620200嘉峪关市相同。与上图第三方数据源对比也缺少对应区县数据

5.经对比有多处具有类似区别,这样会直接导致数据展示有问题或报错,具体体现为,Result result = await CityPickers.showFullPageCityPicker方式时,选择嘉峪关后,由于数初始化并不会将相同的下属区县620200嘉峪关市加入,所以导致你懂的红色页面报错。当使用CityPickers.showCityPicker方式时会展示三级联动选择器,但甘肃省嘉峪关市下级会是空的。
虽然通过踩坑和实践最终放弃了这个第三方,但还是备注下公司数据源转化为第三方所需数据源结构的过程,因为当中也是摸爬滚打有隐藏彩蛋过程。
6.公司数据源由接口获取
下面展示一些 内联代码片

var response = await HttpConfig.getDio().get(getFormAreaDataUrl);

List listProvince = response.data["data"]["top"];
Map  afterProvinceMap = new Map();
listProvince.forEach((element) {
    if (element['is_available']) {
      afterProvinceMap[element['code']] = element['item'].toString();
    }
});

Map mapOther = response.data["data"]["others"];
var afterOtherMap = new Map();
mapOther.forEach((key, value) {
	List listValue = value;
	var mapVaule = Map();
	for (int i = 0; i < listValue.length; i ++) {
  		Map mapWhich = listValue[i];
  		if (mapWhich['is_available']) { //is_available true 有效数据
   	 		var newValueMap = new Map();
    		newValueMap['name'] = mapWhich['item'].toString();
    		mapVaule[mapWhich['code']] = new Map<String, dynamic>.from(newValueMap);
 	 	}
	}
	String keyOne = key.toString().replaceAll('province(', '');
	String keyTwo = keyOne.replaceAll(')', '');
	String keyAfter = keyTwo.replaceAll('city(', '');
	afterOtherMap[keyAfter] = new Map<String, dynamic>.from(mapVaule); //格式化后数据赋值,注此处要重新声明map
});

//传入上面数据调用
onPressed: () async{
	Result result = await CityPickers.showCityPicker(
		context: context,
		provincesData: new Map<String, String>.from(afterProvinceMap),
		citiesData: new Map<String, dynamic>.from(afterOtherMap),
		);
		 if(result != null){
			setState(() {
				widget.dicForm['applyerDetailInfo']['currProvince'] = result.provinceId;
				widget.dicForm['applyerDetailInfo']['currCity'] = result.cityId;
				widget.dicForm['applyerDetailInfo']['currDistrict'] = result.areaId;
			});
		}
},

数据类型说明:
两种初始化方式,但意义不同
1.Map map1 = {‘a’: {‘b’: ‘c’}};
2.Map map2 = new Map(); map2[‘a’] = {‘b’: ‘c’};
第一种字面量直接初始化,环境会自动判断map1的key a 的值为字典map
第二种工厂构造后赋值,表面看是赋值字典map给key a,和方式一没区别。但其实环境是不认的
所以上面代码中会有单独声明等代码
afterProvinceMap[element[‘code’]] = element[‘item’].toString();
provincesData: new Map<String, String>.from(afterProvinceMap),

var newValueMap = new Map();
newValueMap[‘name’] = mapWhich[‘item’].toString();
mapVaule[mapWhich[‘code’]] = new Map<String, dynamic>.from(newValueMap);
afterOtherMap[keyAfter] = new Map<String, dynamic>.from(mapVaule);
citiesData: new Map<String, dynamic>.from(afterOtherMap),

二.自定义省市区选择控件
既然公司现有码表返回数据结构如此,只能自定义,不使用上述以省为根的树结构初始化及查找。
1.此处现有接口获取数据如上所述,省级数据结构为List
下面展示一些 内联代码片

[
  {
    "code":"110000",
    "item":"北京市",
    "is_available":true
  },
 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter是一种跨平台的移动应用开发框架,它使用Dart语言进行编写。在Flutter中,可以通过自定义控件来实现特定的功能或者界面效果。下面是Flutter自定义控件开发的指南: 1. 创建一个新的控件类:在Flutter中,可以通过继承StatefulWidget或者StatelessWidget来创建一个新的控件类。StatefulWidget是有状态的控件,可以根据需要更新状态并重新渲染界面;StatelessWidget是无状态的控件,一旦创建就不会再改变。 2. 实现build方法:在控件类中,需要实现一个build方法,该方法返回一个Widget对象,用于描述控件的外观和行为。可以使用Flutter提供的丰富的Widget库来构建界面,也可以自定义绘制逻辑。 3. 添加属性:通过在控件类中定义属性,可以让用户在使用该控件时传入不同的参数,从而实现控件的可配置性。可以使用构造函数来接收属性,并在build方法中使用这些属性来构建界面。 4. 处理用户交互:如果需要处理用户的点击、滑动等交互操作,可以在控件类中添加相应的回调函数,并将其传递给子控件。子控件可以通过调用回调函数来通知父控件发生了交互事件。 5. 更新状态:如果创建的是有状态的控件,可以通过调用setState方法来更新控件的状态,并触发界面的重新渲染。在setState方法中,可以修改控件的属性值,然后Flutter会自动调用build方法来重新构建界面。 6. 使用自定义控件:在其他地方使用自定义控件时,只需要创建该控件的实例,并将其添加到界面中即可。可以通过设置属性来配置控件的外观和行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值