Flutter中实现中国省份地图

效果展示(这里只展示局部,完全展示违规):

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

在这里插入图片描述

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

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

在Flutter中打开android文件夹

右键android 文件夹,选择flutter -> Open Android module in Android Studio
在这里插入图片描述
点击后就会像打开一个纯Android项目一样(当然还是有些差别的,多了些Flutter相关东西),在这个界面中可以编写原生代码和相应插件。

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

gradle Connect timed out

方法一:

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

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下载问题解决。


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

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中,注释掉一行代码就行。

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

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

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

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中加入下面代码:

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

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;

  
  _ChinaProvinceViewState createState() => _ChinaProvinceViewState();
}

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

  
  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


import 'package:ecology/component/app_bar.dart';
import 'package:flutter/material.dart';

import 'china_province_view.dart';

class MapPage extends StatefulWidget {

  
  _MapPageState createState() => _MapPageState();
}

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

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

  
  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));
  }

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

MapPage 就是地图界面了。

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


该篇文章代码参考自gitee上一个大佬的项目:https://gitee.com/yugecse/coronavirus

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值