Flutter中实现中国省份地图

效果展示:

可以点击省份改变颜色,更多功能可以自行拓展。


注:非完整中国地图!!!

本文用于记录在Flutter项目中安卓端实现中国地图,因为实现过程是通过Flutter调用安卓原生代码实现,所以IOS端不可用,通过本文你还可以学会如何通过Platform Channels在Flutter代码中调用这些原生代码。

在Flutter中打开android文件夹

右键android 文件夹,选择flutter -> Open Android module in Android Studio

点击后就会像打开一个纯Android项目一样(当然还是有些差别的,多了些Flutter相关东西),在这个界面中可以编写原生代码和相应插件。

如果你是第一次打开,它会下载gradle和一大堆构建项目需要的东西,要等好长一会(这个时候你可以买杯咖啡等它构建完成:)),当然过程可能不是那么的顺利,比如你下载gradle过程中会报下面错误(如果没有则忽略下面步骤):

xml 复制代码
gradle Connect timed out

方法一:

然后我就尝试修改仓库配置为阿里镜像:

xml 复制代码
allprojects {
    repositories {
        google()
        maven { url "https://jitpack.io" }
        mavenCentral()
        maven { url "https://maven.aliyun.com/repository/public" } //jcenter & central
    }
}

结果还是一样,科学上网打开也一样,此方法无效!

方法二:

https://services.gradle.org/distributions/ 网址中找到你项目中对应的Gradle版本并下载下来。

解压下载的文件并将其放到你的C:/Users/{用户名}/.gradle/wrapper/dists/gradle-{版本号}-all/{随机字符串}目录下。

如果你不确定应该下载哪个版本的Gradle,你可以查看你的Android工程中的gradle/wrapper/gradle-wrapper.properties文件,该文件中的distributionUrl属性就是你需要的Gradle版本。

可能你的.gradle文件夹移到别的地方了,毕竟这个文件夹占用内存太大,正经人谁放C盘 :)

就算是下载超时,本地文件也会创建.gradle/wrapper/dists/gradle-{版本号}-all/{随机字符串}这个目录的。

此时再Build就可以了,接下来就是大量时间去下载其他依赖...

至此Gradle下载问题解决。


不出意外的话接下来你还会遇到这个问题:

xml 复制代码
Multiple build operations failed.
Could not create task ':flutter_plugin_android_lifecycle:generateDebugUnitTestConfig'.
Could not create task ':image_picker_android:generateDebugUnitTestConfig'.
Could not create task ':path_provider_android:generateDebugUnitTestConfig'.
Could not create task ':shared_preferences_android:generateDebugUnitTestConfig'.
Could not create task ':video_player_android:generateDebugUnitTestConfig'.
Could not create task ':wakelock_plus:generateDebugUnitTestConfig'.
Could not create task ':flutter_plugin_android_lifecycle:generateDebugUnitTestConfig'.
this and base files have different roots: D:\resource\td_ecology_v1\build\flutter_plugin_android_lifecycle and C:\Users\xx\AppData\Local\Pub\Cache\hosted\pub.flutter-io.cn\flutter_plugin_android_lifecycle-2.0.17\android.

不要慌,解决方法如下:

在文件[flutter项目]\android\build.gradle中,注释掉一行代码就行。

xml 复制代码
rootProject.buildDir = '../build'
subprojects {
    //project.buildDir = "${rootProject.buildDir}/${project.name}" // 把这行注释掉,在flutter运行的时候,记得取消这行的注释
}
subprojects {
    project.evaluationDependsOn(':app')
}

tasks.register("clean", Delete) {
    delete rootProject.buildDir
}

注释后再Build就可以构建完成了,记得在Flutter运行的时候,记得取消这行的注释哦,不然会报下面错误:

xml 复制代码
Exception: Gradle build failed to produce an .apk file. It's likely that this file was generated under D:\resource\xxx\build, but the tool couldn't find it.

原生代码编写

核心代码传到了CSDN资源里面,自行下载,不要积分:core文件夹

里面的xml文件要放到 android\app\src\main\res\raw文件夹下奥。

目录如下图所示:

接下来就是在MainActivity中加入下面代码:

kotlin 复制代码
class MainActivity: FlutterActivity() {


    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        GeneratedPluginRegistrant.registerWith(flutterEngine)
        flutterEngine.plugins.add(mutableSetOf<FlutterPlugin>(ChinaProvinceViewFlutterPlugin()))

    }

}

然后返回你的Flutter工程添加下面两个文件:

china_province_view.dart

dart 复制代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

const _ChinaProvinceView_TAG =
    'com.mrper.coronavirus.widgets.china-province-view';

///中国行政区域地图控件
class ChinaProvinceView extends StatefulWidget {

  ChinaProvinceView({
    required this.width,
    required this.onViewCreated,
  })  : assert(width != null && width > 0, '地图宽度必须大于0');

  /// 地图宽度
  final double width;
  /// 视图创建完成的事件
  final Function(int id) onViewCreated;

  @override
  _ChinaProvinceViewState createState() => _ChinaProvinceViewState();
}

class _ChinaProvinceViewState extends State<ChinaProvinceView> {
  /// 地图的宽高比例
  final double _mapWHRatio = 1369.0 / 1141.0;

  @override
  Widget build(BuildContext context) => SizedBox(
      width: widget.width,
      height: widget.width / _mapWHRatio,
      child: AndroidView(
          viewType: _ChinaProvinceView_TAG,
          creationParamsCodec: StandardMessageCodec(),
          onPlatformViewCreated: widget.onViewCreated));
}

class ChinaProvinceViewController {
  late MethodChannel? _methodChannel;
  late EventChannel? _eventChannel;

  ChinaProvinceViewController(int viewId) {
    _methodChannel = MethodChannel('$_ChinaProvinceView_TAG-$viewId');
    _eventChannel = EventChannel('$_ChinaProvinceView_TAG-$viewId-event');
  }

  /// 设置选中的背景色
  set selectedBackgroundColor(int value) => _methodChannel?.invokeMethod(
      'setSelectedBackgroundColor', {'value': value ?? Colors.red.value});

  

  void dispose() {
    if (_methodChannel != null) {
      _methodChannel?.setMethodCallHandler(null);
      _methodChannel = null;
    }
    if (_eventChannel != null) {
      _eventChannel = null;
    }
  }
}

map_page.dart

dart 复制代码
import 'package:ecology/component/app_bar.dart';
import 'package:flutter/material.dart';

import 'china_province_view.dart';

class MapPage extends StatefulWidget {

  @override
  _MapPageState createState() => _MapPageState();
}

class _MapPageState extends State<MapPage> {
  late ChinaProvinceViewController _chinaProvinceViewController;

  void _onChinaProvinceViewCreated(int viewId) {
    _chinaProvinceViewController = ChinaProvinceViewController(viewId)
      ..selectedBackgroundColor = Colors.blue.value;
  }

  @override
  Widget build(BuildContext context) => Container(
    child: SingleChildScrollView(
        child: Column(children: [_buildChinaMapView()])),
  );

  Widget _buildChinaMapView() {
    return Container(
        margin: const EdgeInsets.all(5),
        child: ChinaProvinceView(
            width: MediaQuery.of(context).size.width - 10,
            onViewCreated: _onChinaProvinceViewCreated));
  }

  @override
  void dispose() {
    _chinaProvinceViewController?.dispose();
    super.dispose();
  }
}

MapPage 就是地图界面了。

打完收工,又是加班的一天 ┭┮﹏┭┮


该篇文章代码参考自gitee上一个大佬的项目,暂时找不到了,就不贴链接了。

相关推荐
火柴就是我2 小时前
flutter 之真手势冲突处理
android·flutter
Speed1233 小时前
`mockito` 的核心“打桩”规则
flutter·dart
法的空间3 小时前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
恋猫de小郭3 小时前
Android 将强制应用使用主题图标,你怎么看?
android·前端·flutter
玲珑Felone4 小时前
从flutter源码看其渲染机制
android·flutter
ALLIN1 天前
Flutter 三种方式实现页面切换后保持原页面状态
flutter
Dabei1 天前
Flutter 国际化
flutter
Dabei1 天前
Flutter MQTT 通信文档
flutter
Dabei1 天前
Flutter 中实现 TCP 通信
flutter
孤鸿玉1 天前
ios flutter_echarts 不在当前屏幕 白屏修复
flutter