首页 > 其他分享 >城市地区选择器 级联选择器

城市地区选择器 级联选择器

时间:2023-09-09 16:46:21浏览次数:39  
标签:province city 级联 城市 final county code null 选择器

 

级联选择 Cascader - Ant Design https://ant-design.gitee.io/components/cascader-cn

city_picker_china | Flutter Package https://pub-web.flutter-io.cn/packages/city_picker_china

flutter_city_picker/lib/src/picker.dart at master · cenumi/flutter_city_picker · GitHub https://github.com/cenumi/flutter_city_picker/blob/master/lib/src/picker.dart

import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:collection/collection.dart';

const _nameChildren = 'children';

const _nameCode = 'code';

const _nameName = 'name';

/// The result object returned by Navigator
class CityResult {
  const CityResult({
    required this.code,
    required this.province,
    this.city,
    this.county,
  });

  final String code;
  final String province;
  final String? city;
  final String? county;

  @override
  String toString() {
    return '$province${city == null ? '' : ',$city'}${county == null ? '' : ',$county'}';
  }
}

/// Data object for serialization
class CityNode {
  CityNode(this.name, this.code, [this.children]);

  final String name;
  final String code;
  final List<CityNode>? children;

  factory CityNode.fromJson(Map<String, dynamic> json) {
    final leaf = json[_nameChildren] == null;

    return CityNode(
      json[_nameName] as String,
      json[_nameCode] as String,
      leaf ? null : fromJsonList(json[_nameChildren] as List<dynamic>),
    );
  }

  static List<CityNode> fromJsonList(List<dynamic> list) {
    return list
        .map((e) => CityNode.fromJson(e as Map<String, dynamic>))
        .toList();
  }
}

/// The picker widget
///
/// Normally put it in a dialog or bottomsheet
class CityPicker extends StatefulWidget {
  /// Default constructor
  ///
  /// All column index will be 0
  const CityPicker({Key? key})
      : code = null,
        province = null,
        city = null,
        county = null,
        super(key: key);

  /// Construct the picker by name provided
  ///
  /// The picker column index will stop at the name provided
  /// If any property is null or not found in dataset, the index after will be 0
  const CityPicker.fromName({Key? key, this.province, this.city, this.county})
      : code = null,
        super(key: key);

  /// Construct the pick by code provided
  ///
  /// The picker column index will stop at the code provided
  /// if code is not in dataset, all column index will be 0
  const CityPicker.fromCode({Key? key, this.code})
      : province = null,
        city = null,
        county = null,
        super(key: key);

  /// The city code, e.g. 110111
  final String? code;

  /// The province name, e.g. 北京市
  final String? province;

  /// The city name, e.g. 北京市
  final String? city;

  /// The county name, e.g. 房山区
  final String? county;

  /// Data set from baidu 202104
  /// rootBundle.loadStructuredData will cache the result so no worries
  static Future<List<dynamic>> loadAssets() {
    return rootBundle.loadStructuredData(
      'packages/city_picker_china/assets/data_202104.json',
      (str) async => jsonDecode(str),
    );
  }

  /// Convert the data set to structured data
  static Future<List<CityNode>> loadCityNodes() async {
    return CityNode.fromJsonList(await loadAssets());
  }

  /// Search city infomation by code
  ///
  /// If code is null or not in dataset, null is returned
  static Future<CityResult?> searchWithCode(
    String? code, {
    List<dynamic>? dataSet,
  }) async {
    if (code == null || code.isEmpty) {
      return null;
    }

    final provinces = dataSet ?? await loadAssets();

    for (final province in provinces) {
      if (province[_nameCode] == code) {
        return CityResult(code: code, province: province[_nameName]);
      }
      for (final city in province[_nameChildren]) {
        if (city[_nameCode] == code) {
          return CityResult(
            code: code,
            province: province[_nameName],
            city: city[_nameName],
          );
        }

        for (final county in city[_nameChildren]) {
          if (county[_nameCode] == code) {
            return CityResult(
              code: code,
              province: province[_nameName],
              city: city[_nameName],
              county: county[_nameName],
            );
          }
        }
      }
    }
    return null;
  }

  /// Search city infomation by names
  ///
  /// If [province] is null or not in dataset, null is returned
  /// If any other name is null or not in dataset, the corresponding will be null
  static Future<CityResult?> searchWithName({
    String? province,
    String? city,
    String? county,
    List<dynamic>? dataSet,
  }) async {
    if (province == null || province.isEmpty) {
      return null;
    }

    final provinces = dataSet ?? await loadAssets();

    final provinceInfo = provinces.firstWhereOrNull(
      (element) => element[_nameName] == province,
    );

    if (provinceInfo == null) {
      return null;
    }

    final cityInfo = (city == null || city.isEmpty)
        ? null
        : (provinceInfo[_nameChildren] as List<dynamic>).firstWhereOrNull(
            (element) => element[_nameName] == city,
          );

    if (cityInfo == null) {
      return CityResult(code: provinceInfo[_nameCode], province: province);
    }

    final countyInfo = (county == null || county.isEmpty)
        ? null
        : (cityInfo[_nameChildren] as List<dynamic>).firstWhereOrNull(
            (element) => element[_nameName] == county,
          );

    if (countyInfo == null) {
      return CityResult(
        code: cityInfo[_nameCode],
        province: province,
        city: city,
      );
    }

    return CityResult(
      code: countyInfo[_nameCode],
      province: province,
      city: city,
      county: county,
    );
  }

  @override
  State<CityPicker> createState() => _CityPickerState();
}

class _CityPickerState extends State<CityPicker> {
  List<dynamic>? _data;

  List<String>? _provinces;
  List<String>? _cities;
  List<String>? _counties;

  final _provinceController = FixedExtentScrollController();
  final _cityController = FixedExtentScrollController();
  final _countyController = FixedExtentScrollController();

  @override
  void initState() {
    super.initState();
    () async {
      _data = await CityPicker.loadAssets();

      final result = widget.code != null
          ? await CityPicker.searchWithCode(widget.code!, dataSet: _data)
          : await CityPicker.searchWithName(
              province: widget.province,
              city: widget.city,
              county: widget.county,
              dataSet: _data,
            );

      int indexProvince = 0;
      int indexCity = 0;
      int indexCounty = 0;

      _provinces = _data!.mapIndexed<String>((index, element) {
        final name = element[_nameName];
        if (name == result?.province) {
          indexProvince = index;
        }
        return name;
      }).toList();

      final dataCities = _data![indexProvince][_nameChildren] as List<dynamic>;
      _cities = dataCities.mapIndexed<String>((index, element) {
        final name = element[_nameName];
        if (name == result?.city) {
          indexCity = index;
        }
        return name;
      }).toList();

      final dataCounties = _data![indexProvince][_nameChildren][indexCity]
          [_nameChildren] as List<dynamic>;
      _counties = dataCounties.mapIndexed<String>((index, element) {
        final name = element[_nameName];
        if (name == result?.county) {
          indexCounty = index;
        }
        return name;
      }).toList();

      setState(() {});

      SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
        _provinceController.jumpToItem(indexProvince);
        _cityController.jumpToItem(indexCity);
        _countyController.jumpToItem(indexCounty);
      });
    }();
  }

  @override
  void dispose() {
    _provinceController.dispose();
    _cityController.dispose();
    _countyController.dispose();
    super.dispose();
  }

  void _updateCities() {
    final list = _data![_provinceController.selectedItem][_nameChildren]
        as List<dynamic>;
    _cities = list.map<String>((e) => e[_nameName]).toList();
  }

  void _updateCounties() {
    final list = _data![_provinceController.selectedItem][_nameChildren]
        [_cityController.selectedItem][_nameChildren] as List<dynamic>;
    _counties = list.map<String>((e) => e[_nameName]).toList();
  }

  @override
  Widget build(BuildContext context) {
    final localization = MaterialLocalizations.of(context);

    return Column(
      children: [
        ButtonBar(
          alignment: MainAxisAlignment.spaceBetween,
          children: [
            TextButton(
              onPressed: () => Navigator.pop(context),
              child: Text(localization.cancelButtonLabel),
            ),
            TextButton(
              onPressed: () {
                CityResult? result;
                if (_data == null) {
                  result = null;
                } else {
                  final indexProvince = _provinceController.selectedItem;
                  final indexCity = _cityController.selectedItem;
                  final indexCounty = _countyController.selectedItem;

                  result = CityResult(
                    code: _data![indexProvince][_nameChildren][indexCity]
                        [_nameChildren][indexCounty][_nameCode],
                    province: _provinces![indexProvince],
                    city: _cities![indexCity],
                    county: _counties![indexCounty],
                  );
                }
                Navigator.pop(context, result);
              },
              child: Text(localization.okButtonLabel),
            ),
          ],
        ),
        Expanded(
          child: Row(
            children: [
              _Picker(
                controller: _provinceController,
                data: _provinces ?? [],
                onSelectedItemChanged: () {
                  _cityController.jumpTo(0);
                  _countyController.jumpTo(0);
                  setState(() {
                    _updateCities();
                    _updateCounties();
                  });
                },
              ),
              _Picker(
                controller: _cityController,
                data: _cities ?? [],
                onSelectedItemChanged: () {
                  _countyController.jumpTo(0);
                  setState(() {
                    _updateCounties();
                  });
                },
              ),
              _Picker(
                controller: _countyController,
                data: _counties ?? [],
                onSelectedItemChanged: () {},
              ),
            ],
          ),
        ),
      ],
    );
  }
}

class _Picker extends StatelessWidget {
  const _Picker({
    Key? key,
    required this.data,
    required this.onSelectedItemChanged,
    required this.controller,
  }) : super(key: key);

  final List<String> data;
  final VoidCallback onSelectedItemChanged;
  final FixedExtentScrollController controller;

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: CupertinoPicker.builder(
        itemExtent: 40,
        scrollController: controller,
        onSelectedItemChanged: (_) => onSelectedItemChanged(),
        itemBuilder: (_, index) => Center(
          child: FittedBox(
            child: Text(data[index], style: const TextStyle(fontSize: 14)),
          ),
        ),
        childCount: data.length,
      ),
    );
  }
}

  

 

 

 

 

 

翻译

搜索

复制

标签:province,city,级联,城市,final,county,code,null,选择器
From: https://www.cnblogs.com/papering/p/17689707.html

相关文章

  • 排查下级平台级联至视频汇聚融合平台EasyCVR的层级显示问题
    EasyCVR国标视频综合管理平台是一款以视频为核心的智慧物联应用平台。它基于分布式、负载均衡等流媒体技术进行开发,提供广泛兼容、安全可靠、开放共享的视频综合服务。该平台具备多种功能,包括视频直播、录像、回放、检索、云存储、告警上报、语音对讲、集群、智能AI分析以及平台级......
  • 安防视频监控平台EasyCVR平台+AI智能分析助力构建智慧城市
    EasyCVR平台的智能分析功能在构建智慧城市方面发挥了重要作用。安防行业已经参与智慧城市建设十多年,经历了摸索和探索的阶段。从数字城市到平安城市再到现在的智慧城市,绿色、智能、安全成为智慧城市建设的主题,并在中国迅速发展。EasyCVR通过TSINGSEE青犀视频打造的安防视频云服务,支......
  • 2023“钉耙编程”中国大学生算法设计超级联赛(4)
    1003SimpleSetProblem题意:分别从k个集合中选一个元素组成一个数组\((a_1,a_2,a_3,...,a_k)\),求max\((a_1,a_2,a_3,...,a_k)\)-min\((a_1,a_2,a_3,...,a_k)\)的最小值。分析:我们给每个集合中的元素添加一个id标识它属于哪个集合,然后将所有集合合并并按数值大小从......
  • 如何根据城市名称获取城市编号
    要根据城市名称获取城市编号,首先要创建一个CityCodeUtils工具类publicclassCityCodeUtils{privatestaticPropertiesproperties=newProperties();publicstaticStringDEFAULT_CODE="101010100";privateCityCodeUtils(){}static{......
  • 升哲科技城市级“算力+数字底座”服务亮相2023服贸会
    9月2日至6日,以“开放引领发展,合作共赢未来”为主题的2023年中国国际服务贸易交易会在北京隆重举办。作为城市级数据服务商,升哲科技(SENSORO)连续第四年参加服贸会,携城市级“算力+数字底座”服务及在城市治理领域的广泛应用成果亮相本届服贸会“北京市专精特新展区”,展现科技创新活力......
  • 案例分享丨计讯物联城市内涝监测方案
    方案背景对于极端超标暴雨频发或水面率下降,地表径流不断增大的城市而言,城市内涝是普遍存在的现象。尤其是在下穿隧道、公路桥、立交桥等地,轻则出现积水,导致车辆被淹,重则人民群众的生命安全受到威胁。随着智慧城市的建设进程,城市内涝监测俨然成为智慧城市治理的重要组成部分。 ......
  • Python开发实例(十二)天气预报应用:通过API获取天气数据,让用户输入城市并显示天气情况
    在这个实例中,我们将创建一个天气预报应用,使用Python的requests库来获取天气数据,并让用户输入城市名来显示该城市的天气情况。首先,你需要申请一个天气数据的API密钥。在这个示例中,我们将使用OpenWeatherMap提供的API,你可以在https://openweathermap.org/上注册并获取免费的API密钥......
  • 【CSS】伪类选择器和伪元素选择器
    伪类选择器用于指定所选元素的特殊状态,参考https://developer.mozilla.org/zh-CN/docs/Web/CSS/Pseudo-classes伪元素选择器允许你对被选择元素的特定部分修改样式,不会真的修改dom结构,参考https://developer.mozilla.org/zh-CN/docs/Web/CSS/Pseudo-elements<html><head>......
  • 级联光交的zone配置
    先记录,后补充描述1、创建别名alicreate"自定义别名","1(switchDomainID),0(主机端口ID)"alicreate"member2","1,2;1,3;1,4"alicreate"member3","1,3;1,4;1,5"alishow2、创建zonezonecreate“zonename”,“domainID,storageport;d......
  • jQuery 层次选择器
    jQuery层次选择器(0)测试前的准备工作A.定义测试对象B.定义测试对象的CSS样式C.再定义一些测试用的button。(1)所有后代选择器(AB)所有后代,包括其直接后代及间接后代。(2)直接后代选择器(A>B)直接后代,不包含其孙子后代等。(3)下一个兄弟选择器(A+B)只包含指定对象的下一个兄弟,而不......