当前位置: 首页 > news >正文

flutter使用CupertinoPicker绘制一个传入数据源的省市区选择器

在这里插入图片描述

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}';});});}
http://www.lryc.cn/news/597023.html

相关文章:

  • [Bug | Cursor] import error: No module named ‘data‘
  • C++刷题 - 7.23
  • 【C++】类和对象(中)构造函数、析构函数
  • nrm指南
  • 二级建造师学习笔记-2025
  • 2025 成都航空装备展供需发布:精准匹配,高效成交
  • 货车手机远程启动功能的详细使用步骤及注意事项
  • C#值类型属性的典型问题
  • 基于.Net Core开源的库存订单管理系统
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 主页-微博点赞量Top6实现
  • 粗大误差智能滤除:基于格拉布斯准则与机器学习的数据清洗体系​
  • 深入理解 TCP 协议:Linux 网络传输的可靠基石
  • 【Node.js】使用ts-node运行ts文件时报错: TypeError: Unknown file extension “.ts“ for ts 文件
  • Node.js 倒计时图片服务部署与 Nginx 反向代理实战总结
  • The History of Computers
  • 用 Phi-3 Mini 4K Instruct 实现轻量级模型量化与加载
  • WWDC 25 给自定义 SwiftUI 视图穿上“玻璃外衣”:最新 Liquid Glass 皮肤详解
  • 漫画机器学习播客对话图文版
  • OpenHarmony BUILD.gn中执行脚本
  • 趣玩-Ollama-Llm-Chatrbot
  • 第四章 Freertos物联网实战DHT11温湿度模块
  • 利用aruco标定板标定相机
  • EDoF-ToF: extended depth of field time-of-flight imaging解读, OE 2021
  • C Primer Plus 第6版 编程练习——第10章(上)
  • 2025暑期—05神经网络-BP网络
  • 深入解析预训练语言模型在文本生成中的革命性应用:技术全景与未来挑战
  • 工业微控制器的启动过程以及安全设计所面临的挑战
  • TODAY()-WEEKDAY(TODAY(),2)+1
  • 数据结构系列之二叉搜索树
  • 关于针对 DT_REG 出现红色波浪线的问题(编译错误/IDE警告),以下是 精准解决方案,保持你的代码功能完全不变: