Compare commits
20 Commits
b582025ac7
...
main
Author | SHA1 | Date | |
---|---|---|---|
c4301dee85 | |||
df99810fdf | |||
d4d248d714 | |||
19c0c3bae6 | |||
7cd7360eb8 | |||
c11bc05d01 | |||
c66b8e1ebd | |||
d08a83557d | |||
9c16889c46 | |||
57c0602014 | |||
8dac5bc3b1 | |||
0a6e9c7119 | |||
43ecfb8ca1 | |||
8c59ec203a | |||
74e60b2015 | |||
ae87148c2c | |||
2a889ebbdf | |||
9c1509c59d | |||
e8e1a4d922 | |||
4602f30730 |
16
.github/workflows/publish.yml
vendored
16
.github/workflows/publish.yml
vendored
@ -19,6 +19,18 @@ jobs:
|
||||
skipTests: true
|
||||
flutter: true
|
||||
force: true
|
||||
|
||||
- name: Get Commit Logs
|
||||
id: git_log
|
||||
run: |
|
||||
TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
||||
if [ -z "$TAG" ]; then
|
||||
GIT_LOG=$(git log --pretty=format:'- %s')
|
||||
else
|
||||
GIT_LOG=$(git log --pretty=format:'- %s' $TAG..HEAD)
|
||||
fi
|
||||
echo "git_log=$GIT_LOG" >> $GITHUB_ENV
|
||||
|
||||
- name: Create Release
|
||||
if: steps.package_publisher.outputs.success == 'true'
|
||||
uses: kuloud/Github-Release-Action@v1
|
||||
@ -28,6 +40,8 @@ jobs:
|
||||
tag_name: v${{ steps.package_publisher.outputs.localVersion }}
|
||||
title: Release ${{ steps.package_publisher.outputs.localVersion }}
|
||||
body: |
|
||||
Automated release for version ${{ steps.package_publisher.outputs.localVersion }}
|
||||
Automated release for version ${{ steps.package_publisher.outputs.localVersion }}\n
|
||||
Changes in this release:\n
|
||||
${{ env.git_log }}
|
||||
draft: false
|
||||
prerelease: false
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@ build/
|
||||
**/pubspec.lock
|
||||
.settings/
|
||||
.project
|
||||
**.cxx
|
||||
|
32
CHANGELOG.md
32
CHANGELOG.md
@ -1,3 +1,35 @@
|
||||
## 1.0.14
|
||||
2025-03-12
|
||||
* code lint
|
||||
|
||||
## 1.0.13
|
||||
2025-03-11
|
||||
* 升级amap android sdk版本 10.1.200_loc6.4.9_sea9.7.4 | 2025-03-11
|
||||
* 升级amap iOS sdk版本 10.1.200 | 2024-12-26
|
||||
* 修复问题:android 构建异常,过期接口 io.flutter.view.FlutterMain 替换
|
||||
* 修复问题:android 构建异常,过期接口 PluginRegistry.Registrar 替换
|
||||
|
||||
|
||||
## 1.0.12
|
||||
2024-08-26
|
||||
* code lint
|
||||
|
||||
## 1.0.11
|
||||
2024-08-25
|
||||
* 升级amap iOS sdk版本 10.0.900 | 2024-08-23
|
||||
* code lint
|
||||
|
||||
## 1.0.10
|
||||
2024-08-25
|
||||
* 移除extension实现机制
|
||||
* 添加 getMapContentApprovalNumber / getSatelliteImageApprovalNumber(参见example#ShowMapPage)
|
||||
* 添加 InfoWindowAdapter(参见example#CustomInfoWindowDemoPage),结合 infoWindowEnable 和 BaseInfoWindowAdapter 自行实现具体逻辑
|
||||
* permission_handler 11.3.0 -> 11.3.1
|
||||
|
||||
## 1.0.9
|
||||
2024-08-24
|
||||
* 设置地图语言,支持中文、英文(按SDK描述:1、不能和自定义地图样式同时使用;2、英文状态只在标准地图生效)
|
||||
|
||||
## 1.0.8
|
||||
2024-07-29.
|
||||
* 升级amap android sdk版本 10.0.800_loc6.4.5_sea9.7.2 | 2024-07-19
|
||||
|
13
README.md
13
README.md
@ -6,7 +6,7 @@
|
||||
|
||||
| | Android | iOS |
|
||||
| ----------- | -------------------------- | -------- |
|
||||
| **AMapSDK** | 10.0.800_loc6.4.5_sea9.7.2 | 10.0.800 |
|
||||
| **AMapSDK** | 10.1.200_loc6.4.9_sea9.7.4 | 10.1.200 |
|
||||
| **Support** | SDK 16+ | 12.0+ |
|
||||
|
||||
本插件基于 amap_flutter_map 3.0.0 进行二开的原因:
|
||||
@ -213,8 +213,11 @@ class AMapWidget extends StatefulWidget {
|
||||
///需要应用到地图上的手势集合
|
||||
final Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers;
|
||||
|
||||
///拓展插件,提供更多定制化功能
|
||||
final List<AMapExtension> extensions;
|
||||
/// 设置地图语言
|
||||
final MapLanguage? mapLanguage;
|
||||
|
||||
/// Marker InfoWindow 适配器
|
||||
final InfoWindowAdapter? infoWindowAdapter;
|
||||
}
|
||||
```
|
||||
|
||||
@ -266,4 +269,6 @@ class AMapController {
|
||||
|
||||
google 官方说明地址:https://source.android.com/devices/tech/debug/tagged-pointers
|
||||
|
||||
2. 原本本插件拓展设计的思路是把一些不常用的特性功能做成可插拔的 extension,昨天(2024/07/28)考虑了下,觉得有点过度设计了,包括轻量版 SDK 的接入适配,于是决定后续实现做些调整,尽量贴合 SDK API 实现功能。
|
||||
1. 原本本插件拓展设计的思路是把一些不常用的特性功能做成可插拔的 extension,昨天(2024/07/28)考虑了下,觉得有点过度设计了,包括轻量版 SDK 的接入适配,于是决定后续实现做些调整,尽量贴合 SDK API 实现功能。
|
||||
|
||||
1. 如果模拟器运行遇到 `com.amap.api.col.3sl.dl$b.createContext(GlesUtility.java:73)` 闪退,可尝试切换模拟器图像加速模式为`Software`以获得更好的兼容性。[Issue #27](https://github.com/kuloud/amap_map/issues/27)
|
||||
|
21
analysis_options.yaml
Normal file
21
analysis_options.yaml
Normal file
@ -0,0 +1,21 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
analyzer:
|
||||
exclude:
|
||||
- "**/*.g.dart"
|
||||
- "**/*.freezed.dart"
|
||||
errors:
|
||||
missing_required_param: error
|
||||
missing_return: error
|
||||
invalid_null_aware_operator: error
|
||||
|
||||
linter:
|
||||
rules:
|
||||
always_specify_types: true
|
||||
prefer_final_fields: true
|
||||
prefer_final_in_for_each: true
|
||||
prefer_const_constructors: true
|
||||
prefer_const_declarations: true
|
||||
avoid_print: false
|
||||
avoid_empty_else: true
|
||||
sort_child_properties_last: true
|
@ -8,7 +8,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
classpath 'com.android.tools.build:gradle:3.5.4'
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,8 @@ rootProject.allprojects {
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 34
|
||||
namespace = "com.amap.flutter.map"
|
||||
compileSdkVersion 35
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
@ -33,7 +34,8 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.amap.api:3dmap-location-search:10.0.800_loc6.4.5_sea9.7.2'
|
||||
implementation 'androidx.annotation:annotation:1.8.1'
|
||||
// implementation 'com.amap.api:3dmap-location-search:10.1.200_loc6.4.9_sea9.7.4'
|
||||
implementation 'com.amap.api:navi-3dmap:latest.integration'
|
||||
implementation 'androidx.annotation:annotation:1.9.1'
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,7 @@
|
||||
package com.amap.flutter.map;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.amap.flutter.map.utils.LogUtil;
|
||||
|
||||
@ -12,7 +9,6 @@ import io.flutter.embedding.engine.plugins.FlutterPlugin;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
|
||||
import io.flutter.embedding.engine.plugins.lifecycle.FlutterLifecycleAdapter;
|
||||
import io.flutter.plugin.common.PluginRegistry;
|
||||
|
||||
/**
|
||||
* AmapFlutterMapPlugin
|
||||
@ -23,40 +19,17 @@ public class AMapFlutterMapPlugin implements
|
||||
private static final String CLASS_NAME = "AMapFlutterMapPlugin";
|
||||
private static final String VIEW_TYPE = "com.amap.flutter.map";
|
||||
private Lifecycle lifecycle;
|
||||
private FlutterPluginBinding pluginBinding;
|
||||
|
||||
public AMapFlutterMapPlugin() {
|
||||
}
|
||||
|
||||
public static void registerWith(PluginRegistry.Registrar registrar) {
|
||||
LogUtil.i(CLASS_NAME, "registerWith=====>");
|
||||
|
||||
final Activity activity = registrar.activity();
|
||||
if (activity == null) {
|
||||
LogUtil.w(CLASS_NAME, "activity is null!!!");
|
||||
return;
|
||||
}
|
||||
if (activity instanceof LifecycleOwner) {
|
||||
registrar
|
||||
.platformViewRegistry()
|
||||
.registerViewFactory(
|
||||
VIEW_TYPE,
|
||||
new AMapPlatformViewFactory(
|
||||
registrar.messenger(),
|
||||
() -> ((LifecycleOwner) activity).getLifecycle()));
|
||||
} else {
|
||||
registrar
|
||||
.platformViewRegistry()
|
||||
.registerViewFactory(
|
||||
VIEW_TYPE,
|
||||
new AMapPlatformViewFactory(registrar.messenger(), new ProxyLifecycleProvider(activity)));
|
||||
}
|
||||
}
|
||||
|
||||
// FlutterPlugin
|
||||
|
||||
@Override
|
||||
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
|
||||
LogUtil.i(CLASS_NAME, "onAttachedToEngine==>");
|
||||
this.pluginBinding = binding;
|
||||
binding
|
||||
.getPlatformViewRegistry()
|
||||
.registerViewFactory(
|
||||
@ -78,6 +51,13 @@ public class AMapFlutterMapPlugin implements
|
||||
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
|
||||
LogUtil.i(CLASS_NAME, "onAttachedToActivity==>");
|
||||
lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding);
|
||||
pluginBinding.getPlatformViewRegistry().registerViewFactory(
|
||||
VIEW_TYPE,
|
||||
new AMapPlatformViewFactory(
|
||||
pluginBinding.getBinaryMessenger(),
|
||||
() -> lifecycle
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,6 +51,8 @@ class AMapOptionsBuilder implements AMapOptionsSink, UISettingsSink {
|
||||
|
||||
private Object initialPolygons;
|
||||
|
||||
private String mapLanguage;
|
||||
|
||||
AMapPlatformView build(int id,
|
||||
Context context,
|
||||
BinaryMessenger binaryMessenger,
|
||||
@ -107,6 +109,8 @@ class AMapOptionsBuilder implements AMapOptionsSink, UISettingsSink {
|
||||
List<Object> polygonList = (List<Object>) initialPolygons;
|
||||
aMapPlatformView.getPolygonsController().addByList(polygonList);
|
||||
}
|
||||
|
||||
aMapPlatformView.getMapController().setMapLanguage(mapLanguage);
|
||||
return aMapPlatformView;
|
||||
} catch (Throwable e) {
|
||||
LogUtil.e(CLASS_NAME, "build", e);
|
||||
@ -242,5 +246,9 @@ class AMapOptionsBuilder implements AMapOptionsSink, UISettingsSink {
|
||||
this.initialPolygons = polygonsObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMapLanguage(String mapLanguage) {
|
||||
this.mapLanguage = mapLanguage;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -58,4 +58,11 @@ public interface AMapOptionsSink extends UISettingsSink {
|
||||
public void setInitialPolylines(Object initialPolylines);
|
||||
|
||||
public void setInitialPolygons(Object initialPolygons);
|
||||
|
||||
/**
|
||||
* 设置地图语言
|
||||
*
|
||||
* @param mapLanguage {@link com.amap.api.maps.AMap#CHINESE }, {@link com.amap.api.maps.AMap#ENGLISH }
|
||||
*/
|
||||
void setMapLanguage(String mapLanguage);
|
||||
}
|
||||
|
@ -355,6 +355,13 @@ public class MapController
|
||||
//不实现
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMapLanguage(String mapLanguage) {
|
||||
if (null != amap) {
|
||||
amap.setMapLanguage(mapLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setLogoPosition(int logoPosition) {
|
||||
|
@ -1,14 +1,12 @@
|
||||
package com.amap.flutter.map.overlays.marker;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.amap.api.maps.AMap;
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.maps.model.Marker;
|
||||
import com.amap.api.maps.model.MarkerOptions;
|
||||
import com.amap.api.maps.model.Poi;
|
||||
import com.amap.api.maps.model.*;
|
||||
import com.amap.flutter.map.MyMethodCallHandler;
|
||||
import com.amap.flutter.map.overlays.AbstractOverlayController;
|
||||
import com.amap.flutter.map.utils.Const;
|
||||
|
@ -30,7 +30,8 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.view.FlutterMain;
|
||||
import io.flutter.embedding.engine.FlutterEngine;
|
||||
import io.flutter.embedding.engine.loader.FlutterLoader;
|
||||
|
||||
/**
|
||||
* @author whm
|
||||
@ -44,6 +45,15 @@ public class ConvertUtil {
|
||||
private static final int[] LocationTypeMap = new int[]{MyLocationStyle.LOCATION_TYPE_SHOW, MyLocationStyle.LOCATION_TYPE_FOLLOW, MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE};
|
||||
public static float density;
|
||||
private static String apiKey;
|
||||
private static FlutterLoader flutterLoader; // For asset loading
|
||||
|
||||
public static void initialize(Context context) {
|
||||
flutterLoader = new FlutterLoader();
|
||||
if (!flutterLoader.initialized()) {
|
||||
flutterLoader.startInitialization(context);
|
||||
flutterLoader.ensureInitializationComplete(context, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setPrivacyStatement(Context context, Object object) {
|
||||
if (null == object) {
|
||||
@ -293,6 +303,11 @@ public class ConvertUtil {
|
||||
if (null != logoLeftMargin) {
|
||||
sink.setLogoLeftMargin(toInt(logoLeftMargin));
|
||||
}
|
||||
|
||||
final Object mapLanguage = data.get("mapLanguage");
|
||||
if (null != mapLanguage) {
|
||||
sink.setMapLanguage(toString(mapLanguage));
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
LogUtil.e(CLASS_NAME, "interpretAMapOptions", e);
|
||||
}
|
||||
@ -391,15 +406,15 @@ public class ConvertUtil {
|
||||
case "fromAsset":
|
||||
if (data.size() == 2) {
|
||||
return BitmapDescriptorFactory.fromAsset(
|
||||
FlutterMain.getLookupKeyForAsset(toString(data.get(1))));
|
||||
flutterLoader.getLookupKeyForAsset(toString(data.get(1))));
|
||||
} else {
|
||||
return BitmapDescriptorFactory.fromAsset(
|
||||
FlutterMain.getLookupKeyForAsset(toString(data.get(1)), toString(data.get(2))));
|
||||
flutterLoader.getLookupKeyForAsset(toString(data.get(1)), toString(data.get(2))));
|
||||
}
|
||||
case "fromAssetImage":
|
||||
if (data.size() == 3) {
|
||||
return BitmapDescriptorFactory.fromAsset(
|
||||
FlutterMain.getLookupKeyForAsset(toString(data.get(1))));
|
||||
flutterLoader.getLookupKeyForAsset(toString(data.get(1))));
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"'fromAssetImage' Expected exactly 3 arguments, got: " + data.size());
|
||||
|
@ -26,7 +26,8 @@ if (flutterVersionName == null) {
|
||||
|
||||
|
||||
android {
|
||||
compileSdkVersion 34
|
||||
namespace = "com.amap.flutter.amap_map_example"
|
||||
compileSdkVersion 35
|
||||
|
||||
lint {
|
||||
disable 'InvalidPackage'
|
||||
@ -36,7 +37,7 @@ android {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "com.amap.flutter.amap_map_example"
|
||||
minSdkVersion flutter.minSdkVersion
|
||||
targetSdkVersion 33
|
||||
targetSdkVersion flutter.targetSdkVersion
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
}
|
||||
@ -69,7 +70,7 @@ android {
|
||||
jniLibs.srcDirs = ['libs']
|
||||
}
|
||||
}
|
||||
ndkVersion '25.1.8937393'
|
||||
ndkVersion '27.0.12077973'
|
||||
}
|
||||
dependencies {
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
<application
|
||||
android:allowNativeHeapPointerTagging="false"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="amap_map_example">
|
||||
|
@ -1,4 +1,15 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.useAndroidX=true
|
||||
## For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
#
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx1024m -XX:MaxPermSize=256m
|
||||
org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
#
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. For more details, visit
|
||||
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
||||
# org.gradle.parallel=true
|
||||
#Tue Mar 11 22:34:19 CST 2025
|
||||
android.enableJetifier=true
|
||||
#android.enableR8=true
|
||||
android.useAndroidX=true
|
||||
|
@ -1,6 +1,6 @@
|
||||
#Fri Jun 23 08:50:38 CEST 2017
|
||||
#Tue Mar 11 20:48:47 CST 2025
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip
|
||||
|
@ -18,8 +18,8 @@ pluginManagement {
|
||||
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "7.4.2" apply false
|
||||
id "org.jetbrains.kotlin.android" version "1.7.10" apply false
|
||||
id "com.android.application" version "8.9.0" apply false
|
||||
id "org.jetbrains.kotlin.android" version "2.1.10" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
|
@ -1,7 +1,7 @@
|
||||
PODS:
|
||||
- AMap3DMap (10.0.800):
|
||||
- AMap3DMap (10.1.200):
|
||||
- AMapFoundation (>= 1.8.0)
|
||||
- amap_map (1.0.3):
|
||||
- amap_map (1.0.8):
|
||||
- AMap3DMap
|
||||
- Flutter
|
||||
- AMapFoundation (1.8.2)
|
||||
@ -28,8 +28,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
AMap3DMap: 6761e0381f517978312e4f795ce77b2b9f6781a6
|
||||
amap_map: 8773e5cacc760edf208b1e6e61000241d26385fa
|
||||
AMap3DMap: 220e48934bc6553a15251c8c86f581a802787506
|
||||
amap_map: 5be213f350872f6ea406be964031572ab9a0d6e1
|
||||
AMapFoundation: 9885c48fc3a78fdfb84a0299a2293e56ea3c9fec
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class AnimatedCategoryItem extends StatelessWidget {
|
||||
AnimatedCategoryItem({
|
||||
super.key,
|
||||
required double startDelayFraction,
|
||||
required this.controller,
|
||||
required this.child,
|
||||
@ -27,7 +28,7 @@ class AnimatedCategoryItem extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: controller,
|
||||
builder: (context, child) {
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: topPaddingAnimation.value),
|
||||
child: child,
|
||||
|
@ -172,7 +172,6 @@ class _CategoryHeader extends StatelessWidget {
|
||||
margin: margin,
|
||||
child: Material(
|
||||
shape: RoundedRectangleBorder(borderRadius: borderRadius),
|
||||
color: colorScheme.onBackground,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
@ -198,10 +197,7 @@ class _CategoryHeader extends StatelessWidget {
|
||||
padding: const EdgeInsetsDirectional.only(start: 8),
|
||||
child: Text(
|
||||
category.toDisplayTitle(),
|
||||
style:
|
||||
Theme.of(context).textTheme.headlineMedium!.apply(
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -268,7 +264,6 @@ class CategoryDemoItem extends StatelessWidget {
|
||||
return Material(
|
||||
// Makes integration tests possible.
|
||||
key: ValueKey(demo.describe),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: MergeSemantics(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
@ -292,8 +287,7 @@ class CategoryDemoItem extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
demo.title,
|
||||
style: textTheme.titleMedium!
|
||||
.apply(color: colorScheme.onSurface),
|
||||
style: textTheme.titleMedium,
|
||||
),
|
||||
Text(
|
||||
demo.subtitle,
|
||||
@ -305,7 +299,7 @@ class CategoryDemoItem extends StatelessWidget {
|
||||
Divider(
|
||||
thickness: 1,
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -2,9 +2,9 @@ import 'dart:collection';
|
||||
|
||||
import 'package:amap_map_example/main.dart';
|
||||
import 'package:amap_map_example/pages/interactive/map_ui_options.dart';
|
||||
import 'package:amap_map_example/pages/map/change_map_lang.dart';
|
||||
import 'package:amap_map_example/pages/map/limit_map_bounds.dart';
|
||||
import 'package:amap_map_example/pages/map/map_my_location.dart';
|
||||
import 'package:amap_map_example/pages/map/map_with_extension_page.dart';
|
||||
import 'package:amap_map_example/pages/map/show_map_page.dart';
|
||||
import 'package:amap_map_example/pages/overlays/custom_info_window.dart';
|
||||
import 'package:amap_map_example/pages/overlays/marker_config.dart';
|
||||
@ -18,8 +18,7 @@ class DemoConfiguration {
|
||||
final WidgetBuilder buildRoute;
|
||||
}
|
||||
|
||||
List<Demo> allDemos() =>
|
||||
mapDemos() + interactiveDemos() + overlayDemos() + extensionDemos();
|
||||
List<Demo> allDemos() => mapDemos() + interactiveDemos() + overlayDemos();
|
||||
|
||||
List<Demo> mapDemos() {
|
||||
return [
|
||||
@ -47,6 +46,14 @@ List<Demo> mapDemos() {
|
||||
configurations: [
|
||||
DemoConfiguration(buildRoute: (context) => LimitMapBoundsPage())
|
||||
]),
|
||||
Demo(
|
||||
title: '地图显示语言',
|
||||
category: DemoCategory.basic,
|
||||
subtitle: '演示限定手机屏幕显示地图的范围',
|
||||
slug: 'map-lang',
|
||||
configurations: [
|
||||
DemoConfiguration(buildRoute: (context) => ChangeMapLangPage())
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
@ -84,19 +91,6 @@ List<Demo> overlayDemos() {
|
||||
];
|
||||
}
|
||||
|
||||
List<Demo> extensionDemos() {
|
||||
return [
|
||||
Demo(
|
||||
title: '辅助信息获取',
|
||||
category: DemoCategory.extension,
|
||||
subtitle: '获取审图号',
|
||||
slug: 'extension-info',
|
||||
configurations: [
|
||||
DemoConfiguration(buildRoute: (context) => MapWithExtensionPage())
|
||||
])
|
||||
];
|
||||
}
|
||||
|
||||
Map<String?, Demo> slugToDemo(BuildContext context) {
|
||||
return LinkedHashMap<String?, Demo>.fromIterable(
|
||||
allDemos(),
|
||||
|
@ -4,10 +4,55 @@ import 'package:amap_map_example/category_list_item.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:amap_map_example/data/demos.dart';
|
||||
import 'package:amap_map_example/routes.dart';
|
||||
import 'package:amap_map_example/theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
void main() {
|
||||
runApp(MaterialApp(
|
||||
themeMode: ThemeMode.light,
|
||||
onGenerateRoute: RouteConfig.onGenerateRoute,
|
||||
home: AMapDemo()));
|
||||
}
|
||||
|
||||
enum DemoCategory {
|
||||
basic,
|
||||
interactive,
|
||||
overlay,
|
||||
extension;
|
||||
|
||||
String toDisplayTitle() {
|
||||
switch (this) {
|
||||
case basic:
|
||||
return '创建地图';
|
||||
case interactive:
|
||||
return '与地图交互';
|
||||
case overlay:
|
||||
return '在地图上绘制';
|
||||
case extension:
|
||||
return '拓展插件';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Demo {
|
||||
const Demo({
|
||||
required this.title,
|
||||
required this.category,
|
||||
required this.subtitle,
|
||||
// Parameters below are required for non-study demos.
|
||||
this.slug,
|
||||
this.configurations = const [],
|
||||
}) : assert(slug != null);
|
||||
|
||||
final String title;
|
||||
final DemoCategory category;
|
||||
final String subtitle;
|
||||
final String? slug;
|
||||
final List<DemoConfiguration> configurations;
|
||||
|
||||
String get describe => '$slug@${category.name}';
|
||||
}
|
||||
|
||||
final List<Permission> needPermissionList = [
|
||||
Permission.location,
|
||||
Permission.storage,
|
||||
@ -79,13 +124,6 @@ class _AMapDemoState extends State<AMapDemo>
|
||||
category: DemoCategory.overlay,
|
||||
demos: overlayDemos(),
|
||||
)),
|
||||
AnimatedCategoryItem(
|
||||
startDelayFraction: 0.15,
|
||||
controller: _animationController,
|
||||
child: CategoryListItem(
|
||||
category: DemoCategory.extension,
|
||||
demos: extensionDemos(),
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
@ -100,49 +138,4 @@ class _AMapDemoState extends State<AMapDemo>
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
runApp(MaterialApp(
|
||||
theme: ThemeData(colorScheme: DemoThemeData.lightColorScheme),
|
||||
themeMode: ThemeMode.light,
|
||||
onGenerateRoute: RouteConfig.onGenerateRoute,
|
||||
home: AMapDemo()));
|
||||
}
|
||||
|
||||
enum DemoCategory {
|
||||
basic,
|
||||
interactive,
|
||||
overlay,
|
||||
extension;
|
||||
|
||||
String toDisplayTitle() {
|
||||
switch (this) {
|
||||
case basic:
|
||||
return '创建地图';
|
||||
case interactive:
|
||||
return '与地图交互';
|
||||
case overlay:
|
||||
return '在地图上绘制';
|
||||
case extension:
|
||||
return '拓展插件';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Demo {
|
||||
const Demo({
|
||||
required this.title,
|
||||
required this.category,
|
||||
required this.subtitle,
|
||||
// Parameters below are required for non-study demos.
|
||||
this.slug,
|
||||
this.configurations = const [],
|
||||
}) : assert(slug != null);
|
||||
|
||||
final String title;
|
||||
final DemoCategory category;
|
||||
final String subtitle;
|
||||
final String? slug;
|
||||
final List<DemoConfiguration> configurations;
|
||||
|
||||
String get describe => '$slug@${category.name}';
|
||||
}
|
||||
|
@ -4,10 +4,10 @@ import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class GesturesDemoPage extends StatefulWidget {
|
||||
GesturesDemoPage({Key? key}) : super(key: key);
|
||||
GesturesDemoPage({super.key});
|
||||
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
State<GesturesDemoPage> createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<GesturesDemoPage> {
|
||||
@ -71,7 +71,7 @@ class _BodyState extends State<GesturesDemoPage> {
|
||||
},
|
||||
),
|
||||
];
|
||||
Widget _gesturesOptiosWeidget() {
|
||||
Widget gesturesOptiosWeidget() {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(5),
|
||||
child: Column(
|
||||
@ -103,7 +103,7 @@ class _BodyState extends State<GesturesDemoPage> {
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Container(
|
||||
child: _gesturesOptiosWeidget(),
|
||||
child: gesturesOptiosWeidget(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -4,13 +4,12 @@ import 'package:amap_map_example/widgets/amap_radio_group.dart';
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'package:x_common/utils/logger.dart';
|
||||
|
||||
class MapUIDemoPage extends StatefulWidget {
|
||||
MapUIDemoPage({Key? key}) : super(key: key);
|
||||
MapUIDemoPage({super.key});
|
||||
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
State<MapUIDemoPage> createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<MapUIDemoPage> {
|
||||
@ -53,7 +52,7 @@ class _BodyState extends State<MapUIDemoPage> {
|
||||
);
|
||||
|
||||
//ui控制
|
||||
final List<Widget> _uiOptions = [
|
||||
final List<Widget> uiOptions = [
|
||||
AMapSwitchButton(
|
||||
label: Text('显示路况'),
|
||||
defaultValue: _trafficEnabled,
|
||||
@ -101,7 +100,7 @@ class _BodyState extends State<MapUIDemoPage> {
|
||||
),
|
||||
];
|
||||
|
||||
Widget _uiOptionsWidget() {
|
||||
Widget uiOptionsWidget() {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(5),
|
||||
child: Column(
|
||||
@ -111,7 +110,7 @@ class _BodyState extends State<MapUIDemoPage> {
|
||||
Text('UI操作', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
child: AMapGradView(childrenWidgets: _uiOptions),
|
||||
child: AMapGradView(childrenWidgets: uiOptions),
|
||||
),
|
||||
AMapRadioGroup<LogoPosition?>(
|
||||
groupLabel: 'Logo位置',
|
||||
@ -170,7 +169,7 @@ class _BodyState extends State<MapUIDemoPage> {
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Container(
|
||||
child: _uiOptionsWidget(),
|
||||
child: uiOptionsWidget(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -4,10 +4,10 @@ import 'package:amap_map_example/widgets/amap_gridview.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MoveCameraDemoPage extends StatefulWidget {
|
||||
MoveCameraDemoPage({Key? key}) : super(key: key);
|
||||
const MoveCameraDemoPage({super.key});
|
||||
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
State<MoveCameraDemoPage> createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<MoveCameraDemoPage> {
|
||||
@ -20,23 +20,23 @@ class _BodyState extends State<MoveCameraDemoPage> {
|
||||
onCameraMove: _onCameraMove,
|
||||
onCameraMoveEnd: _onCameraMoveEnd,
|
||||
);
|
||||
List<Widget> _optionsWidget = [
|
||||
List<Widget> optionsWidget = [
|
||||
_createMyFloatButton('改变显示区域', _changeLatLngBounds),
|
||||
_createMyFloatButton('改变中心点', _changeCameraPosition),
|
||||
_createMyFloatButton('改变缩放级别到18', _changeCameraZoom),
|
||||
_createMyFloatButton('按照像素移动地图', _scrollBy),
|
||||
];
|
||||
|
||||
Widget _cameraOptions() {
|
||||
Widget cameraOptions() {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
child: AMapGradView(
|
||||
childrenWidgets: _optionsWidget,
|
||||
childrenWidgets: optionsWidget,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -45,7 +45,7 @@ class _BodyState extends State<MoveCameraDemoPage> {
|
||||
}
|
||||
|
||||
return ConstrainedBox(
|
||||
constraints: BoxConstraints.expand(),
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: Column(
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
@ -54,7 +54,7 @@ class _BodyState extends State<MoveCameraDemoPage> {
|
||||
minHeight: MediaQuery.of(context).size.height * 0.7),
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.7,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: amap,
|
||||
@ -66,28 +66,28 @@ class _BodyState extends State<MoveCameraDemoPage> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
InkResponse(
|
||||
onTap: _zoomIn,
|
||||
child: Container(
|
||||
child: Icon(
|
||||
width: 40,
|
||||
height: 40,
|
||||
color: Colors.blue,
|
||||
child: const Icon(
|
||||
Icons.add,
|
||||
color: Colors.white,
|
||||
),
|
||||
width: 40,
|
||||
height: 40,
|
||||
color: Colors.blue,
|
||||
),
|
||||
onTap: _zoomIn,
|
||||
),
|
||||
InkResponse(
|
||||
onTap: _zoomOut,
|
||||
child: Container(
|
||||
child: Icon(
|
||||
color: Colors.blue,
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: const Icon(
|
||||
Icons.remove,
|
||||
color: Colors.white,
|
||||
),
|
||||
color: Colors.blue,
|
||||
width: 40,
|
||||
height: 40,
|
||||
),
|
||||
onTap: _zoomOut,
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -103,16 +103,16 @@ class _BodyState extends State<MoveCameraDemoPage> {
|
||||
? Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
color: Colors.grey,
|
||||
padding: EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
_currentZoom!,
|
||||
style: TextStyle(color: Colors.white),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
)
|
||||
: SizedBox(),
|
||||
: const SizedBox(),
|
||||
Container(
|
||||
child: _cameraOptions(),
|
||||
child: cameraOptions(),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -141,7 +141,7 @@ class _BodyState extends State<MoveCameraDemoPage> {
|
||||
void _changeCameraPosition() {
|
||||
_mapController?.moveCamera(
|
||||
CameraUpdate.newCameraPosition(
|
||||
CameraPosition(
|
||||
const CameraPosition(
|
||||
//中心点
|
||||
target: LatLng(31.230378, 121.473658),
|
||||
//缩放级别
|
||||
@ -184,8 +184,8 @@ class _BodyState extends State<MoveCameraDemoPage> {
|
||||
_mapController?.moveCamera(
|
||||
CameraUpdate.newLatLngBounds(
|
||||
LatLngBounds(
|
||||
southwest: LatLng(33.789925, 104.838326),
|
||||
northeast: LatLng(38.740688, 114.647472)),
|
||||
southwest: const LatLng(33.789925, 104.838326),
|
||||
northeast: const LatLng(38.740688, 114.647472)),
|
||||
15.0),
|
||||
animated: true,
|
||||
);
|
||||
@ -204,16 +204,16 @@ class _BodyState extends State<MoveCameraDemoPage> {
|
||||
return TextButton(
|
||||
onPressed: onPressed,
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all(
|
||||
shape: WidgetStateProperty.all(
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))),
|
||||
//文字颜色
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
foregroundColor: WidgetStateProperty.all(Colors.white),
|
||||
//水波纹颜色
|
||||
overlayColor: MaterialStateProperty.all(Colors.blueAccent),
|
||||
overlayColor: WidgetStateProperty.all(Colors.blueAccent),
|
||||
//背景颜色
|
||||
backgroundColor: MaterialStateProperty.resolveWith((states) {
|
||||
backgroundColor: WidgetStateProperty.resolveWith((states) {
|
||||
//设置按下时的背景颜色
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.blueAccent;
|
||||
}
|
||||
//默认背景颜色
|
||||
|
@ -3,10 +3,10 @@ import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PoiClickDemoPage extends StatefulWidget {
|
||||
PoiClickDemoPage({Key? key}) : super(key: key);
|
||||
PoiClickDemoPage({super.key});
|
||||
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
State<PoiClickDemoPage> createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<PoiClickDemoPage> {
|
||||
|
@ -32,16 +32,16 @@ class _SnapShotState extends State<SnapshotPage> {
|
||||
child: TextButton(
|
||||
child: Text('截屏'),
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(
|
||||
shape: WidgetStateProperty.all(RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10))),
|
||||
//文字颜色
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
foregroundColor: WidgetStateProperty.all(Colors.white),
|
||||
//水波纹颜色
|
||||
overlayColor: MaterialStateProperty.all(Colors.blueAccent),
|
||||
overlayColor: WidgetStateProperty.all(Colors.blueAccent),
|
||||
//背景颜色
|
||||
backgroundColor: MaterialStateProperty.resolveWith((states) {
|
||||
backgroundColor: WidgetStateProperty.resolveWith((states) {
|
||||
//设置按下时的背景颜色
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.blueAccent;
|
||||
}
|
||||
//默认背景颜色
|
||||
|
73
example/lib/pages/map/change_map_lang.dart
Normal file
73
example/lib/pages/map/change_map_lang.dart
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2024 kuloud
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/widgets/amap_radio_group.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ChangeMapLangPage extends StatefulWidget {
|
||||
ChangeMapLangPage({super.key});
|
||||
|
||||
@override
|
||||
State<ChangeMapLangPage> createState() => _PageBodyState();
|
||||
}
|
||||
|
||||
class _PageBodyState extends State<ChangeMapLangPage> {
|
||||
MapLanguage? _mapLang;
|
||||
final Map<String, MapLanguage> _radioValueMap = {
|
||||
'中文': MapLanguage.chinese,
|
||||
'English': MapLanguage.english,
|
||||
};
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_mapLang = MapLanguage.chinese;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
//创建地图
|
||||
final AMapWidget map = AMapWidget(
|
||||
mapLanguage: _mapLang,
|
||||
);
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Container(
|
||||
height: MediaQuery.of(context).size.height * 0.6,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: map,
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Container(
|
||||
child: AMapRadioGroup(
|
||||
groupLabel: '地图语言',
|
||||
groupValue: _mapLang,
|
||||
radioValueMap: _radioValueMap,
|
||||
onChanged: (value) => {
|
||||
setState(() {
|
||||
_mapLang = value;
|
||||
})
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -3,10 +3,10 @@ import 'package:amap_map_example/widgets/amap_radio_group.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ChangeMapTypePage extends StatefulWidget {
|
||||
ChangeMapTypePage({Key? key}) : super(key: key);
|
||||
ChangeMapTypePage({super.key});
|
||||
|
||||
@override
|
||||
_PageBodyState createState() => _PageBodyState();
|
||||
State<ChangeMapTypePage> createState() => _PageBodyState();
|
||||
}
|
||||
|
||||
class _PageBodyState extends State<ChangeMapTypePage> {
|
||||
|
@ -4,16 +4,16 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class CustomMapStylePage extends StatefulWidget {
|
||||
CustomMapStylePage({Key? key}) : super(key: key);
|
||||
CustomMapStylePage({super.key});
|
||||
|
||||
@override
|
||||
_CustomMapStyleState createState() => _CustomMapStyleState();
|
||||
State<CustomMapStylePage> createState() => _CustomMapStyleState();
|
||||
}
|
||||
|
||||
class _CustomMapStyleState extends State<CustomMapStylePage> {
|
||||
bool _mapCreated = false;
|
||||
|
||||
CustomStyleOptions _customStyleOptions = CustomStyleOptions(false);
|
||||
final CustomStyleOptions _customStyleOptions = CustomStyleOptions(false);
|
||||
//加载自定义地图样式
|
||||
void _loadCustomData() async {
|
||||
ByteData styleByteData = await rootBundle.load('assets/style.data');
|
||||
|
@ -3,10 +3,10 @@ import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LimitMapBoundsPage extends StatefulWidget {
|
||||
LimitMapBoundsPage({Key? key}) : super(key: key);
|
||||
LimitMapBoundsPage({super.key});
|
||||
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
State<LimitMapBoundsPage> createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<LimitMapBoundsPage> {
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -8,13 +6,15 @@ import 'package:flutter/services.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
|
||||
class AllMapConfigDemoPage extends StatefulWidget {
|
||||
const AllMapConfigDemoPage({super.key});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _MapUiBodyState();
|
||||
}
|
||||
|
||||
class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
//默认显示在北京天安门
|
||||
static final CameraPosition _kInitialPosition = const CameraPosition(
|
||||
static const CameraPosition _kInitialPosition = CameraPosition(
|
||||
target: LatLng(39.909187, 116.397451),
|
||||
zoom: 10.0,
|
||||
);
|
||||
@ -54,10 +54,10 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
|
||||
late AMapController _controller;
|
||||
|
||||
CustomStyleOptions _customStyleOptions = CustomStyleOptions(false);
|
||||
final CustomStyleOptions _customStyleOptions = CustomStyleOptions(false);
|
||||
|
||||
///自定义定位小蓝点
|
||||
MyLocationStyleOptions _myLocationStyleOptions =
|
||||
final MyLocationStyleOptions _myLocationStyleOptions =
|
||||
MyLocationStyleOptions(false);
|
||||
@override
|
||||
void initState() {
|
||||
@ -100,7 +100,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
onPoiTouched: _onMapPoiTouched,
|
||||
);
|
||||
|
||||
Widget _mapTypeRadio(String label, MapType radioValue) {
|
||||
Widget mapTypeRadio(String label, MapType radioValue) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
@ -118,18 +118,18 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
);
|
||||
}
|
||||
|
||||
final List<Widget> _mapTypeList = [
|
||||
_mapTypeRadio('普通地图', MapType.normal),
|
||||
_mapTypeRadio('卫星地图', MapType.satellite),
|
||||
_mapTypeRadio('导航地图', MapType.navi),
|
||||
_mapTypeRadio('公交地图', MapType.bus),
|
||||
_mapTypeRadio('黑夜模式', MapType.night),
|
||||
final List<Widget> mapTypeList = [
|
||||
mapTypeRadio('普通地图', MapType.normal),
|
||||
mapTypeRadio('卫星地图', MapType.satellite),
|
||||
mapTypeRadio('导航地图', MapType.navi),
|
||||
mapTypeRadio('公交地图', MapType.bus),
|
||||
mapTypeRadio('黑夜模式', MapType.night),
|
||||
];
|
||||
|
||||
//ui控制
|
||||
final List<Widget> _uiOptions = [
|
||||
final List<Widget> uiOptions = [
|
||||
AMapSwitchButton(
|
||||
label: Text('显示路况'),
|
||||
label: const Text('显示路况'),
|
||||
defaultValue: _trafficEnabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -138,7 +138,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
},
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('显示3D建筑物'),
|
||||
label: const Text('显示3D建筑物'),
|
||||
defaultValue: _buildingsEnabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -147,7 +147,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
},
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('显示指南针'),
|
||||
label: const Text('显示指南针'),
|
||||
defaultValue: _compassEnabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -156,7 +156,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
},
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('显示地图文字'),
|
||||
label: const Text('显示地图文字'),
|
||||
defaultValue: _labelsEnabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -165,7 +165,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
},
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('显示比例尺'),
|
||||
label: const Text('显示比例尺'),
|
||||
defaultValue: _scaleEnabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -174,7 +174,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
},
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('点击Poi'),
|
||||
label: const Text('点击Poi'),
|
||||
defaultValue: _touchPoiEnabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -183,7 +183,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
},
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('自定义地图'),
|
||||
label: const Text('自定义地图'),
|
||||
defaultValue: _customStyleOptions.enabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -196,7 +196,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
//手势开关
|
||||
final List<Widget> gesturesOptions = [
|
||||
AMapSwitchButton(
|
||||
label: Text('旋转'),
|
||||
label: const Text('旋转'),
|
||||
defaultValue: _rotateGesturesEnabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -205,7 +205,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
},
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('滑动'),
|
||||
label: const Text('滑动'),
|
||||
defaultValue: _scrollGesturesEnabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -214,7 +214,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
},
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('倾斜'),
|
||||
label: const Text('倾斜'),
|
||||
defaultValue: _tiltGesturesEnabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -223,7 +223,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
},
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('缩放'),
|
||||
label: const Text('缩放'),
|
||||
defaultValue: _zoomGesturesEnabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -233,34 +233,34 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
),
|
||||
];
|
||||
|
||||
Widget _mapTypeOptions() {
|
||||
Widget mapTypeOptions() {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text('地图样式', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
const Text('地图样式', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
child: createGridView(_mapTypeList),
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: createGridView(mapTypeList),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _myLocationStyleContainer() {
|
||||
Widget myLocationStyleContainer() {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// Text('定位小蓝点', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
AMapSwitchButton(
|
||||
label:
|
||||
Text('定位小蓝点', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
label: const Text('定位小蓝点',
|
||||
style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
defaultValue: _myLocationStyleOptions.enabled,
|
||||
onSwitchChanged: (value) => {
|
||||
setState(() {
|
||||
@ -273,33 +273,33 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _uiOptionsWidget() {
|
||||
Widget uiOptionsWidget() {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text('UI操作', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
const Text('UI操作', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
child: createGridView(_uiOptions),
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: createGridView(uiOptions),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _gesturesOptiosWeidget() {
|
||||
Widget gesturesOptiosWeidget() {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text('手势控制', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
const Text('手势控制', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: createGridView(gesturesOptions),
|
||||
),
|
||||
],
|
||||
@ -307,13 +307,13 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _optionsItem() {
|
||||
Widget optionsItem() {
|
||||
return Column(
|
||||
children: [
|
||||
_mapTypeOptions(),
|
||||
_myLocationStyleContainer(),
|
||||
_uiOptionsWidget(),
|
||||
_gesturesOptiosWeidget(),
|
||||
mapTypeOptions(),
|
||||
myLocationStyleContainer(),
|
||||
uiOptionsWidget(),
|
||||
gesturesOptiosWeidget(),
|
||||
TextButton(
|
||||
child: const Text('moveCamera到首开'),
|
||||
onPressed: _moveCameraToShoukai,
|
||||
@ -337,7 +337,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Container(
|
||||
child: _optionsItem(),
|
||||
child: optionsItem(),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -366,7 +366,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
Widget createGridView(List<Widget> widgets) {
|
||||
return GridView.count(
|
||||
primary: false,
|
||||
physics: new NeverScrollableScrollPhysics(),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
//水平子Widget之间间距
|
||||
crossAxisSpacing: 1.0,
|
||||
//垂直子Widget之间间距
|
||||
@ -381,7 +381,7 @@ class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
|
||||
//移动地图中心点到首开广场
|
||||
void _moveCameraToShoukai() {
|
||||
_controller.moveCamera(CameraUpdate.newCameraPosition(CameraPosition(
|
||||
_controller.moveCamera(CameraUpdate.newCameraPosition(const CameraPosition(
|
||||
target: LatLng(39.993306, 116.473004),
|
||||
zoom: 18,
|
||||
tilt: 30,
|
||||
|
@ -3,9 +3,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
class MyLocationPage extends StatefulWidget {
|
||||
MyLocationPage({Key? key}) : super(key: key);
|
||||
MyLocationPage({super.key});
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
State<MyLocationPage> createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<MyLocationPage> {
|
||||
|
@ -1,83 +0,0 @@
|
||||
// Copyright 2023-2024 kuloud
|
||||
// Copyright 2020 lbs.amap.com
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
// import 'package:amap_map_extensions/amap_map_extensions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
|
||||
class MapWithExtensionPage extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() => _MapWithExtensionPageState();
|
||||
}
|
||||
|
||||
class _MapWithExtensionPageState extends State<MapWithExtensionPage> {
|
||||
List<Widget> _approvalNumberWidget = <Widget>[];
|
||||
// final _extension = AmapMapExtensions();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final AMapWidget map = AMapWidget(
|
||||
onMapCreated: onMapCreated,
|
||||
// extensions: [_extension],
|
||||
);
|
||||
|
||||
return ConstrainedBox(
|
||||
constraints: BoxConstraints.expand(),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: map,
|
||||
),
|
||||
Positioned(
|
||||
right: 10,
|
||||
bottom: 15,
|
||||
child: Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: _approvalNumberWidget),
|
||||
))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
late AMapController _mapController;
|
||||
void onMapCreated(AMapController controller) {
|
||||
setState(() {
|
||||
_mapController = controller;
|
||||
getApprovalNumber();
|
||||
});
|
||||
}
|
||||
|
||||
/// 获取审图号
|
||||
void getApprovalNumber() async {
|
||||
// //普通地图审图号
|
||||
// String mapContentApprovalNumber =
|
||||
// (await _extension.getMapContentApprovalNumber())!;
|
||||
// //卫星地图审图号
|
||||
// String satelliteImageApprovalNumber =
|
||||
// (await _extension.getSatelliteImageApprovalNumber())!;
|
||||
// setState(() {
|
||||
// _approvalNumberWidget.add(Text(mapContentApprovalNumber));
|
||||
// _approvalNumberWidget.add(Text(satelliteImageApprovalNumber));
|
||||
// });
|
||||
// print('地图审图号(普通地图): $mapContentApprovalNumber');
|
||||
// print('地图审图号(卫星地图): $satelliteImageApprovalNumber');
|
||||
}
|
||||
}
|
@ -2,10 +2,10 @@ import 'package:amap_map/amap_map.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MinMaxZoomDemoPage extends StatefulWidget {
|
||||
MinMaxZoomDemoPage({Key? key}) : super(key: key);
|
||||
const MinMaxZoomDemoPage({super.key});
|
||||
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
State<MinMaxZoomDemoPage> createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<MinMaxZoomDemoPage> {
|
||||
@ -22,7 +22,7 @@ class _BodyState extends State<MinMaxZoomDemoPage> {
|
||||
minMaxZoomPreference: MinMaxZoomPreference(_minZoom, _maxZoom),
|
||||
);
|
||||
return ConstrainedBox(
|
||||
constraints: BoxConstraints.expand(),
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
@ -40,24 +40,24 @@ class _BodyState extends State<MinMaxZoomDemoPage> {
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
color: Colors.grey,
|
||||
padding: EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
'当前限制的最小最大缩放级别是:[$_minZoom, $_maxZoom]',
|
||||
style: TextStyle(color: Colors.blue),
|
||||
style: const TextStyle(color: Colors.blue),
|
||||
),
|
||||
),
|
||||
_currentZoom != null
|
||||
? Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
color: Colors.grey,
|
||||
padding: EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
_currentZoom!,
|
||||
style: TextStyle(color: Colors.white),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
))
|
||||
: SizedBox(),
|
||||
: const SizedBox(),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -69,7 +69,7 @@ class _BodyState extends State<MinMaxZoomDemoPage> {
|
||||
children: [
|
||||
InkResponse(
|
||||
child: Container(
|
||||
child: Icon(
|
||||
child: const Icon(
|
||||
Icons.add,
|
||||
color: Colors.white,
|
||||
),
|
||||
@ -81,7 +81,7 @@ class _BodyState extends State<MinMaxZoomDemoPage> {
|
||||
),
|
||||
InkResponse(
|
||||
child: Container(
|
||||
child: Icon(
|
||||
child: const Icon(
|
||||
Icons.remove,
|
||||
color: Colors.white,
|
||||
),
|
||||
|
@ -3,7 +3,7 @@ import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MultiMapDemoPage extends StatefulWidget {
|
||||
const MultiMapDemoPage();
|
||||
const MultiMapDemoPage({super.key});
|
||||
@override
|
||||
State<StatefulWidget> createState() => _MultiMapDemoState();
|
||||
}
|
||||
@ -14,7 +14,7 @@ class _MultiMapDemoState extends State<MultiMapDemoPage> {
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Column(
|
||||
child: const Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
|
@ -8,7 +8,7 @@ class ShowMapPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ShowMapPageState extends State<ShowMapPage> {
|
||||
List<Widget> _approvalNumberWidget = <Widget>[];
|
||||
final List<Widget> _approvalNumberWidget = <Widget>[];
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final AMapWidget map = AMapWidget(
|
||||
@ -43,23 +43,23 @@ class _ShowMapPageState extends State<ShowMapPage> {
|
||||
void onMapCreated(AMapController controller) {
|
||||
setState(() {
|
||||
_mapController = controller;
|
||||
// getApprovalNumber();
|
||||
getApprovalNumber();
|
||||
});
|
||||
}
|
||||
|
||||
/// 获取审图号
|
||||
void getApprovalNumber() async {
|
||||
// //普通地图审图号
|
||||
// String mapContentApprovalNumber =
|
||||
// (await _mapController.getMapContentApprovalNumber())!;
|
||||
// //卫星地图审图号
|
||||
// String satelliteImageApprovalNumber =
|
||||
// (await _mapController.getSatelliteImageApprovalNumber())!;
|
||||
// setState(() {
|
||||
// _approvalNumberWidget.add(Text(mapContentApprovalNumber));
|
||||
// _approvalNumberWidget.add(Text(satelliteImageApprovalNumber));
|
||||
// });
|
||||
// print('地图审图号(普通地图): $mapContentApprovalNumber');
|
||||
// print('地图审图号(卫星地图): $satelliteImageApprovalNumber');
|
||||
//普通地图审图号
|
||||
String mapContentApprovalNumber =
|
||||
(await _mapController.getMapContentApprovalNumber());
|
||||
//卫星地图审图号
|
||||
String satelliteImageApprovalNumber =
|
||||
(await _mapController.getSatelliteImageApprovalNumber());
|
||||
setState(() {
|
||||
_approvalNumberWidget.add(Text(mapContentApprovalNumber));
|
||||
_approvalNumberWidget.add(Text(satelliteImageApprovalNumber));
|
||||
});
|
||||
print('地图审图号(普通地图): $mapContentApprovalNumber');
|
||||
print('地图审图号(卫星地图): $satelliteImageApprovalNumber');
|
||||
}
|
||||
}
|
||||
|
@ -18,20 +18,17 @@ class CustomInfoWindowDemoPage extends StatefulWidget {
|
||||
class _State extends State<CustomInfoWindowDemoPage> {
|
||||
static final LatLng mapCenter = const LatLng(39.909187, 116.397451);
|
||||
|
||||
Map<String, Marker> _markers = <String, Marker>{};
|
||||
final Map<String, Marker> _markers = <String, Marker>{};
|
||||
BitmapDescriptor? _markerIcon;
|
||||
String? selectedMarkerId;
|
||||
bool showInfoWindow = false;
|
||||
AMapController? _controller;
|
||||
|
||||
final _infoWindowExtension = InfoWindowExtension(
|
||||
infoWindow: Container(
|
||||
color: Colors.lightBlue.shade400,
|
||||
child: Text('info'),
|
||||
),
|
||||
option: InfoWindowOption(
|
||||
latLng: mapCenter, offset: EdgeInsets.only(bottom: 32)));
|
||||
|
||||
Future<void> _onMapCreated(AMapController controller) async {}
|
||||
Future<void> _onMapCreated(AMapController controller) async {
|
||||
setState(() {
|
||||
_controller = controller;
|
||||
});
|
||||
}
|
||||
|
||||
void _add() {
|
||||
final int markerCount = _markers.length;
|
||||
@ -42,8 +39,8 @@ class _State extends State<CustomInfoWindowDemoPage> {
|
||||
position: markPostion,
|
||||
icon: _markerIcon!,
|
||||
infoWindow: InfoWindow(title: '第 $markerCount 个Marker'),
|
||||
onTap: (markerId) => _onMarkerTapped(markerId),
|
||||
onDragEnd: (markerId, endPosition) =>
|
||||
onTap: (String markerId) => _onMarkerTapped(markerId),
|
||||
onDragEnd: (String markerId, LatLng endPosition) =>
|
||||
_onMarkerDragEnd(markerId, endPosition),
|
||||
);
|
||||
|
||||
@ -80,7 +77,7 @@ class _State extends State<CustomInfoWindowDemoPage> {
|
||||
}
|
||||
|
||||
void _removeAll() {
|
||||
if (_markers.length > 0) {
|
||||
if (_markers.isNotEmpty) {
|
||||
setState(() {
|
||||
_markers.clear();
|
||||
selectedMarkerId = null.toString();
|
||||
@ -90,7 +87,7 @@ class _State extends State<CustomInfoWindowDemoPage> {
|
||||
|
||||
void _changeInfo() async {
|
||||
final Marker marker = _markers[selectedMarkerId]!;
|
||||
final String newTitle = marker.infoWindow.title! + '*';
|
||||
final String newTitle = '${marker.infoWindow.title!}*';
|
||||
if (selectedMarkerId != null) {
|
||||
setState(() {
|
||||
_markers[selectedMarkerId!] = marker.copyWith(
|
||||
@ -168,7 +165,7 @@ class _State extends State<CustomInfoWindowDemoPage> {
|
||||
setState(() {
|
||||
showInfoWindow = value;
|
||||
_markers[selectedMarkerId!] = marker.copyWith(
|
||||
// visibleParam: value,
|
||||
visibleParam: value,
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -186,18 +183,12 @@ class _State extends State<CustomInfoWindowDemoPage> {
|
||||
Widget build(BuildContext context) {
|
||||
///以下几种获取自定图片的方式使用其中一种即可。
|
||||
//最简单的方式
|
||||
if (null == _markerIcon) {
|
||||
_markerIcon = BitmapDescriptor.fromIconPath('assets/location_marker.png');
|
||||
}
|
||||
_markerIcon ??= BitmapDescriptor.fromIconPath('assets/location_marker.png');
|
||||
|
||||
_infoWindowExtension.option?.show =
|
||||
_markers[selectedMarkerId] != null && showInfoWindow;
|
||||
_infoWindowExtension.option?.latLng = _markers[selectedMarkerId]?.position;
|
||||
|
||||
final AMapWidget map = AMapWidget(
|
||||
AMapWidget map = AMapWidget(
|
||||
onMapCreated: _onMapCreated,
|
||||
markers: Set<Marker>.of(_markers.values),
|
||||
extensions: [_infoWindowExtension],
|
||||
infoWindowAdapter: CustomInfoWindowAdapter(_controller, selectedMarkerId),
|
||||
);
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
@ -205,7 +196,7 @@ class _State extends State<CustomInfoWindowDemoPage> {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Container(
|
||||
height: MediaQuery.of(context).size.height * 0.6,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
@ -221,64 +212,64 @@ class _State extends State<CustomInfoWindowDemoPage> {
|
||||
Column(
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('添加'),
|
||||
onPressed: _add,
|
||||
child: const Text('添加'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('移除'),
|
||||
onPressed:
|
||||
(selectedMarkerId == null) ? null : _remove,
|
||||
child: const Text('移除'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('更新InfoWidow'),
|
||||
onPressed:
|
||||
(selectedMarkerId == null) ? null : _changeInfo,
|
||||
child: const Text('更新InfoWidow'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改锚点'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changeAnchor,
|
||||
child: const Text('修改锚点'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改透明度'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changeAlpha,
|
||||
child: const Text('修改透明度'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
onPressed: _markers.isNotEmpty ? _removeAll : null,
|
||||
child: const Text('全部移除'),
|
||||
onPressed: _markers.length > 0 ? _removeAll : null,
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('允许拖动'),
|
||||
label: const Text('允许拖动'),
|
||||
onSwitchChanged: (selectedMarkerId == null)
|
||||
? null
|
||||
: _toggleDraggable,
|
||||
defaultValue: false,
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('显示'),
|
||||
label: const Text('显示'),
|
||||
onSwitchChanged: (selectedMarkerId == null)
|
||||
? null
|
||||
: _toggleVisible,
|
||||
defaultValue: true,
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改坐标'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changePosition,
|
||||
child: const Text('修改坐标'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改旋转角度'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changeRotation,
|
||||
child: const Text('修改旋转角度'),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -293,3 +284,42 @@ class _State extends State<CustomInfoWindowDemoPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CustomInfoWindowAdapter extends BaseInfoWindowAdapter {
|
||||
CustomInfoWindowAdapter(super.controller, this.selectedMarkerId);
|
||||
|
||||
final String? selectedMarkerId;
|
||||
|
||||
@override
|
||||
Widget? buildInfoWindowContent(BuildContext context, Marker marker) {
|
||||
if (marker.id != selectedMarkerId) {
|
||||
return null;
|
||||
}
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
boxShadow: <BoxShadow>[
|
||||
const BoxShadow(
|
||||
color: Colors.black26,
|
||||
blurRadius: 4.0,
|
||||
spreadRadius: 2.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
marker.infoWindow.title ?? 'No Title',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
marker.infoWindow.snippet ?? 'No Snippet',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class MarkerAddAfterMapPage extends StatefulWidget {
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
State<MarkerAddAfterMapPage> createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<MarkerAddAfterMapPage> {
|
||||
@ -14,16 +14,16 @@ class _BodyState extends State<MarkerAddAfterMapPage> {
|
||||
LatLng _currentLatLng = defaultPosition;
|
||||
//添加一个marker
|
||||
void _addMarker() {
|
||||
final _markerPosition =
|
||||
final markerPosition =
|
||||
LatLng(_currentLatLng.latitude, _currentLatLng.longitude + 2 / 1000);
|
||||
final Marker marker = Marker(
|
||||
position: _markerPosition,
|
||||
position: markerPosition,
|
||||
//使用默认hue的方式设置Marker的图标
|
||||
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueOrange),
|
||||
);
|
||||
//调用setState触发AMapWidget的更新,从而完成marker的添加
|
||||
setState(() {
|
||||
_currentLatLng = _markerPosition;
|
||||
_currentLatLng = markerPosition;
|
||||
//将新的marker添加到map里
|
||||
_markers[marker.id] = marker;
|
||||
});
|
||||
@ -33,16 +33,16 @@ class _BodyState extends State<MarkerAddAfterMapPage> {
|
||||
return TextButton(
|
||||
onPressed: onPressed,
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all(
|
||||
shape: WidgetStateProperty.all(
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))),
|
||||
//文字颜色
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
foregroundColor: WidgetStateProperty.all(Colors.white),
|
||||
//水波纹颜色
|
||||
overlayColor: MaterialStateProperty.all(Colors.blueAccent),
|
||||
overlayColor: WidgetStateProperty.all(Colors.blueAccent),
|
||||
//背景颜色
|
||||
backgroundColor: MaterialStateProperty.resolveWith((states) {
|
||||
backgroundColor: WidgetStateProperty.resolveWith((states) {
|
||||
//设置按下时的背景颜色
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.blueAccent;
|
||||
}
|
||||
//默认背景颜色
|
||||
|
@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class MarkerAddWithMapPage extends StatefulWidget {
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
State<MarkerAddWithMapPage> createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<MarkerAddWithMapPage> {
|
||||
|
@ -19,7 +19,7 @@ class MarkerConfigDemoPage extends StatefulWidget {
|
||||
class _State extends State<MarkerConfigDemoPage> {
|
||||
static final LatLng mapCenter = const LatLng(39.909187, 116.397451);
|
||||
|
||||
Map<String, Marker> _markers = <String, Marker>{};
|
||||
final Map<String, Marker> _markers = <String, Marker>{};
|
||||
BitmapDescriptor? _markerIcon;
|
||||
String? selectedMarkerId;
|
||||
|
||||
@ -27,11 +27,11 @@ class _State extends State<MarkerConfigDemoPage> {
|
||||
LatLng latLng = LatLng(mapCenter.latitude + sin(pi / 12.0) / 20.0,
|
||||
mapCenter.longitude + cos(pi / 12.0) / 20.0);
|
||||
try {
|
||||
print('-latLng---------${latLng}');
|
||||
print('-latLng---------$latLng');
|
||||
ScreenCoordinate coordinate = await controller.toScreenCoordinate(latLng);
|
||||
print('-coordinate---------${coordinate}');
|
||||
print('-coordinate---------$coordinate');
|
||||
LatLng reLatLng = await controller.fromScreenCoordinate(coordinate);
|
||||
print('-reLatLng---------${reLatLng}');
|
||||
print('-reLatLng---------$reLatLng');
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
@ -85,7 +85,6 @@ class _State extends State<MarkerConfigDemoPage> {
|
||||
onDragEnd: (markerId, endPosition) =>
|
||||
_onMarkerDragEnd(markerId, endPosition),
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_markers[marker.id] = marker;
|
||||
});
|
||||
@ -119,7 +118,7 @@ class _State extends State<MarkerConfigDemoPage> {
|
||||
}
|
||||
|
||||
void _removeAll() {
|
||||
if (_markers.length > 0) {
|
||||
if (_markers.isNotEmpty) {
|
||||
setState(() {
|
||||
_markers.clear();
|
||||
selectedMarkerId = null.toString();
|
||||
@ -129,7 +128,7 @@ class _State extends State<MarkerConfigDemoPage> {
|
||||
|
||||
void _changeInfo() async {
|
||||
final Marker marker = _markers[selectedMarkerId]!;
|
||||
final String newTitle = marker.infoWindow.title! + '*';
|
||||
final String newTitle = '${marker.infoWindow.title!}*';
|
||||
if (selectedMarkerId != null) {
|
||||
setState(() {
|
||||
_markers[selectedMarkerId!] = marker.copyWith(
|
||||
@ -233,14 +232,12 @@ class _State extends State<MarkerConfigDemoPage> {
|
||||
Widget build(BuildContext context) {
|
||||
///以下几种获取自定图片的方式使用其中一种即可。
|
||||
//最简单的方式
|
||||
if (null == _markerIcon) {
|
||||
_markerIcon = BitmapDescriptor.fromIconPath('assets/location_marker.png');
|
||||
}
|
||||
_markerIcon ??= BitmapDescriptor.fromIconPath('assets/location_marker.png');
|
||||
|
||||
//通过BitmapDescriptor.fromAssetImage的方式获取图片
|
||||
// _createMarkerImageFromAsset(context);
|
||||
_createMarkerImageFromAsset(context);
|
||||
//通过BitmapDescriptor.fromBytes的方式获取图片
|
||||
// _createMarkerImageFromBytes(context);
|
||||
_createMarkerImageFromBytes(context);
|
||||
|
||||
final AMapWidget map = AMapWidget(
|
||||
onMapCreated: _onMapCreated,
|
||||
@ -268,64 +265,64 @@ class _State extends State<MarkerConfigDemoPage> {
|
||||
Column(
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('添加'),
|
||||
onPressed: _add,
|
||||
child: const Text('添加'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('移除'),
|
||||
onPressed:
|
||||
(selectedMarkerId == null) ? null : _remove,
|
||||
child: const Text('移除'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('更新InfoWidow'),
|
||||
onPressed:
|
||||
(selectedMarkerId == null) ? null : _changeInfo,
|
||||
child: const Text('更新InfoWidow'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改锚点'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changeAnchor,
|
||||
child: const Text('修改锚点'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改透明度'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changeAlpha,
|
||||
child: const Text('修改透明度'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
onPressed: _markers.isNotEmpty ? _removeAll : null,
|
||||
child: const Text('全部移除'),
|
||||
onPressed: _markers.length > 0 ? _removeAll : null,
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('允许拖动'),
|
||||
label: const Text('允许拖动'),
|
||||
onSwitchChanged: (selectedMarkerId == null)
|
||||
? null
|
||||
: _toggleDraggable,
|
||||
defaultValue: false,
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('显示'),
|
||||
label: const Text('显示'),
|
||||
onSwitchChanged: (selectedMarkerId == null)
|
||||
? null
|
||||
: _toggleVisible,
|
||||
defaultValue: true,
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改坐标'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changePosition,
|
||||
child: const Text('修改坐标'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改旋转角度'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changeRotation,
|
||||
child: const Text('修改旋转角度'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -3,17 +3,19 @@ import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MarkerCustomIconPage extends StatefulWidget {
|
||||
const MarkerCustomIconPage({super.key});
|
||||
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
State<MarkerCustomIconPage> createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<MarkerCustomIconPage> {
|
||||
static final LatLng markerPosition = const LatLng(39.909187, 116.397451);
|
||||
static const LatLng markerPosition = LatLng(39.909187, 116.397451);
|
||||
final Map<String, Marker> _initMarkerMap = <String, Marker>{};
|
||||
String? _currentMarkerId;
|
||||
bool _hasInitMarker = false;
|
||||
static final String _startIconPath = 'assets/start.png';
|
||||
static final String _endIconPath = 'assets/end.png';
|
||||
static const String _startIconPath = 'assets/start.png';
|
||||
static const String _endIconPath = 'assets/end.png';
|
||||
String _iconPath = _startIconPath;
|
||||
void _initMarker(BuildContext context) async {
|
||||
if (_hasInitMarker) {
|
||||
@ -42,16 +44,16 @@ class _BodyState extends State<MarkerCustomIconPage> {
|
||||
return TextButton(
|
||||
onPressed: onPressed,
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all(
|
||||
shape: WidgetStateProperty.all(
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))),
|
||||
//文字颜色
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
foregroundColor: WidgetStateProperty.all(Colors.white),
|
||||
//水波纹颜色
|
||||
overlayColor: MaterialStateProperty.all(Colors.blueAccent),
|
||||
overlayColor: WidgetStateProperty.all(Colors.blueAccent),
|
||||
//背景颜色
|
||||
backgroundColor: MaterialStateProperty.resolveWith((states) {
|
||||
backgroundColor: WidgetStateProperty.resolveWith((states) {
|
||||
//设置按下时的背景颜色
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.blueAccent;
|
||||
}
|
||||
//默认背景颜色
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
@ -24,7 +23,7 @@ class _State extends State<PolygonDemoPage> {
|
||||
Colors.pink,
|
||||
];
|
||||
|
||||
Map<String, Polygon> _polygons = <String, Polygon>{};
|
||||
final Map<String, Polygon> _polygons = <String, Polygon>{};
|
||||
String? selectedPolygonId;
|
||||
|
||||
void _onMapCreated(AMapController controller) {}
|
||||
@ -111,7 +110,7 @@ class _State extends State<PolygonDemoPage> {
|
||||
List<LatLng> currentPoints = polygon.points;
|
||||
List<LatLng> newPoints = <LatLng>[];
|
||||
newPoints.addAll(currentPoints);
|
||||
newPoints.add(LatLng(39.828809, 116.360364));
|
||||
newPoints.add(const LatLng(39.828809, 116.360364));
|
||||
|
||||
setState(() {
|
||||
_polygons[selectedPolygonId!] = polygon.copyWith(
|
||||
@ -134,7 +133,7 @@ class _State extends State<PolygonDemoPage> {
|
||||
Widget build(BuildContext context) {
|
||||
final AMapWidget map = AMapWidget(
|
||||
initialCameraPosition:
|
||||
CameraPosition(target: LatLng(39.828809, 116.360364), zoom: 13),
|
||||
const CameraPosition(target: LatLng(39.828809, 116.360364), zoom: 13),
|
||||
onMapCreated: _onMapCreated,
|
||||
polygons: Set<Polygon>.of(_polygons.values),
|
||||
);
|
||||
@ -160,42 +159,42 @@ class _State extends State<PolygonDemoPage> {
|
||||
Column(
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('添加'),
|
||||
onPressed: _add,
|
||||
child: const Text('添加'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('删除'),
|
||||
onPressed:
|
||||
(selectedPolygonId == null) ? null : _remove,
|
||||
child: const Text('删除'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改边框宽度'),
|
||||
onPressed: (selectedPolygonId == null)
|
||||
? null
|
||||
: _changeStrokeWidth,
|
||||
child: const Text('修改边框宽度'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('修改边框和填充色'),
|
||||
onPressed: (selectedPolygonId == null)
|
||||
? null
|
||||
: _changeColors,
|
||||
child: const Text('修改边框和填充色'),
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('显示'),
|
||||
label: const Text('显示'),
|
||||
onSwitchChanged: (selectedPolygonId == null)
|
||||
? null
|
||||
: _toggleVisible,
|
||||
defaultValue: true,
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改坐标'),
|
||||
onPressed: (selectedPolygonId == null)
|
||||
? null
|
||||
: _changePoints,
|
||||
child: const Text('修改坐标'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
@ -23,7 +22,7 @@ class _State extends State<PolylineDemoPage> {
|
||||
Colors.green,
|
||||
Colors.pink,
|
||||
];
|
||||
Map<String, Polyline> _polylines = <String, Polyline>{};
|
||||
final Map<String, Polyline> _polylines = <String, Polyline>{};
|
||||
String? selectedPolylineId;
|
||||
|
||||
void _onMapCreated(AMapController controller) {}
|
||||
@ -64,7 +63,7 @@ class _State extends State<PolylineDemoPage> {
|
||||
}
|
||||
|
||||
void _changeWidth() {
|
||||
final Polyline? selectedPolyline = _polylines[selectedPolylineId]!;
|
||||
final Polyline? selectedPolyline = _polylines[selectedPolylineId];
|
||||
//有选中的Polyline
|
||||
if (selectedPolyline != null) {
|
||||
double currentWidth = selectedPolyline.width;
|
||||
@ -109,7 +108,7 @@ class _State extends State<PolylineDemoPage> {
|
||||
}
|
||||
|
||||
void _changeCapType() {
|
||||
final Polyline? polyline = _polylines[selectedPolylineId]!;
|
||||
final Polyline? polyline = _polylines[selectedPolylineId];
|
||||
if (polyline == null) {
|
||||
return;
|
||||
}
|
||||
@ -172,7 +171,7 @@ class _State extends State<PolylineDemoPage> {
|
||||
List<LatLng> currentPoints = polyline.points;
|
||||
List<LatLng> newPoints = <LatLng>[];
|
||||
newPoints.addAll(currentPoints);
|
||||
newPoints.add(LatLng(39.835347, 116.34575));
|
||||
newPoints.add(const LatLng(39.835347, 116.34575));
|
||||
|
||||
setState(() {
|
||||
_polylines[selectedPolylineId!] = polyline.copyWith(
|
||||
@ -219,28 +218,28 @@ class _State extends State<PolylineDemoPage> {
|
||||
Column(
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('添加'),
|
||||
onPressed: _add,
|
||||
child: const Text('添加'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('删除'),
|
||||
onPressed:
|
||||
(selectedPolylineId == null) ? null : _remove,
|
||||
child: const Text('删除'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改线宽'),
|
||||
onPressed: (selectedPolylineId == null)
|
||||
? null
|
||||
: _changeWidth,
|
||||
child: const Text('修改线宽'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改透明度'),
|
||||
onPressed: (selectedPolylineId == null)
|
||||
? null
|
||||
: _changeAlpha,
|
||||
child: const Text('修改透明度'),
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('显示'),
|
||||
label: const Text('显示'),
|
||||
onSwitchChanged: (selectedPolylineId == null)
|
||||
? null
|
||||
: _toggleVisible,
|
||||
@ -251,34 +250,34 @@ class _State extends State<PolylineDemoPage> {
|
||||
Column(
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('修改颜色'),
|
||||
onPressed: (selectedPolylineId == null)
|
||||
? null
|
||||
: _changeColor,
|
||||
child: const Text('修改颜色'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改线头样式'),
|
||||
onPressed: (selectedPolylineId == null)
|
||||
? null
|
||||
: _changeCapType,
|
||||
child: const Text('修改线头样式'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改连接样式'),
|
||||
onPressed: (selectedPolylineId == null)
|
||||
? null
|
||||
: _changeJointType,
|
||||
child: const Text('修改连接样式'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改虚线类型'),
|
||||
onPressed: (selectedPolylineId == null)
|
||||
? null
|
||||
: _changeDashLineType,
|
||||
child: const Text('修改虚线类型'),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改坐标'),
|
||||
onPressed: (selectedPolylineId == null)
|
||||
? null
|
||||
: _changePoints,
|
||||
child: const Text('修改坐标'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
@ -22,7 +21,7 @@ class _State extends State<PolylineGeodesicDemoPage> {
|
||||
Colors.green,
|
||||
Colors.pink,
|
||||
];
|
||||
Map<String, Polyline> _polylines = <String, Polyline>{};
|
||||
final Map<String, Polyline> _polylines = <String, Polyline>{};
|
||||
late String selectedPolylineId;
|
||||
AMapController? _controller;
|
||||
|
||||
@ -89,16 +88,16 @@ class _State extends State<PolylineGeodesicDemoPage> {
|
||||
child: TextButton(
|
||||
onPressed: _add,
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(
|
||||
shape: WidgetStateProperty.all(RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10))),
|
||||
//文字颜色
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
foregroundColor: WidgetStateProperty.all(Colors.white),
|
||||
//水波纹颜色
|
||||
overlayColor: MaterialStateProperty.all(Colors.blueAccent),
|
||||
overlayColor: WidgetStateProperty.all(Colors.blueAccent),
|
||||
//背景颜色
|
||||
backgroundColor: MaterialStateProperty.resolveWith((states) {
|
||||
backgroundColor: WidgetStateProperty.resolveWith((states) {
|
||||
//设置按下时的背景颜色
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.blueAccent;
|
||||
}
|
||||
//默认背景颜色
|
||||
|
@ -13,7 +13,7 @@ class PolylineTextureDemoPage extends StatefulWidget {
|
||||
class _State extends State<PolylineTextureDemoPage> {
|
||||
_State();
|
||||
|
||||
Map<String, Polyline> _polylines = <String, Polyline>{};
|
||||
final Map<String, Polyline> _polylines = <String, Polyline>{};
|
||||
late String selectedPolylineId;
|
||||
|
||||
void _onMapCreated(AMapController controller) {}
|
||||
@ -76,16 +76,16 @@ class _State extends State<PolylineTextureDemoPage> {
|
||||
child: TextButton(
|
||||
onPressed: _add,
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(
|
||||
shape: WidgetStateProperty.all(RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10))),
|
||||
//文字颜色
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
foregroundColor: WidgetStateProperty.all(Colors.white),
|
||||
//水波纹颜色
|
||||
overlayColor: MaterialStateProperty.all(Colors.blueAccent),
|
||||
overlayColor: WidgetStateProperty.all(Colors.blueAccent),
|
||||
//背景颜色
|
||||
backgroundColor: MaterialStateProperty.resolveWith((states) {
|
||||
backgroundColor: WidgetStateProperty.resolveWith((states) {
|
||||
//设置按下时的背景颜色
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.blueAccent;
|
||||
}
|
||||
//默认背景颜色
|
||||
|
@ -23,7 +23,7 @@ class Path {
|
||||
}
|
||||
|
||||
class RouteConfig {
|
||||
static List<Path> _paths = [
|
||||
static final List<Path> _paths = [
|
||||
Path(
|
||||
r'^/([\w-]+)$',
|
||||
(context, match) => DemoPage(slug: match),
|
||||
|
@ -1,20 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DemoThemeData {
|
||||
static const _lightFillColor = Colors.black;
|
||||
static const ColorScheme lightColorScheme = ColorScheme(
|
||||
primary: Color(0xFFB93C5D),
|
||||
primaryContainer: Color(0xFF117378),
|
||||
secondary: Color(0xFFEFF3F3),
|
||||
secondaryContainer: Color(0xFFFAFBFB),
|
||||
background: Color(0xFFE6EBEB),
|
||||
surface: Color(0xFFFAFBFB),
|
||||
onBackground: Colors.white,
|
||||
error: _lightFillColor,
|
||||
onError: _lightFillColor,
|
||||
onPrimary: _lightFillColor,
|
||||
onSecondary: Color(0xFF322942),
|
||||
onSurface: Color(0xFF241E30),
|
||||
brightness: Brightness.light,
|
||||
);
|
||||
}
|
@ -11,13 +11,12 @@ class AMapGradView extends StatefulWidget {
|
||||
final double? childAspectRatio;
|
||||
|
||||
AMapGradView(
|
||||
{Key? key,
|
||||
{super.key,
|
||||
this.crossAxisCount,
|
||||
this.childAspectRatio,
|
||||
required this.childrenWidgets})
|
||||
: super(key: key);
|
||||
required this.childrenWidgets});
|
||||
@override
|
||||
_GradViewState createState() => _GradViewState();
|
||||
State<AMapGradView> createState() => _GradViewState();
|
||||
}
|
||||
|
||||
class _GradViewState extends State<AMapGradView> {
|
||||
@ -25,7 +24,7 @@ class _GradViewState extends State<AMapGradView> {
|
||||
Widget build(BuildContext context) {
|
||||
return GridView.count(
|
||||
primary: false,
|
||||
physics: new NeverScrollableScrollPhysics(),
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
//水平子Widget之间间距
|
||||
crossAxisSpacing: 1.0,
|
||||
//垂直子Widget之间间距
|
||||
|
@ -7,15 +7,14 @@ class AMapRadioGroup<T> extends StatefulWidget {
|
||||
final Map<String, T>? radioValueMap;
|
||||
final ValueChanged<T?>? onChanged;
|
||||
AMapRadioGroup(
|
||||
{Key? key,
|
||||
{super.key,
|
||||
this.groupLabel,
|
||||
this.groupValue,
|
||||
this.radioValueMap,
|
||||
this.onChanged})
|
||||
: super(key: key);
|
||||
this.onChanged});
|
||||
|
||||
@override
|
||||
_AMapRadioGroupState<T> createState() => _AMapRadioGroupState<T>();
|
||||
State<AMapRadioGroup<T>> createState() => _AMapRadioGroupState<T>();
|
||||
}
|
||||
|
||||
class _AMapRadioGroupState<T> extends State<AMapRadioGroup<T>> {
|
||||
@ -24,14 +23,14 @@ class _AMapRadioGroupState<T> extends State<AMapRadioGroup<T>> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_groupValue = (widget.groupValue ?? null) as T?;
|
||||
_groupValue = (widget.groupValue);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<Widget> radioList = <Widget>[];
|
||||
_groupValue = (widget.groupValue ?? null) as T?;
|
||||
Widget _myRadio(String label, dynamic radioValue) {
|
||||
_groupValue = (widget.groupValue);
|
||||
Widget myRadio(String label, dynamic radioValue) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
@ -39,11 +38,11 @@ class _AMapRadioGroupState<T> extends State<AMapRadioGroup<T>> {
|
||||
Radio<T>(
|
||||
value: radioValue,
|
||||
groupValue: _groupValue,
|
||||
onChanged: (T? _value) {
|
||||
onChanged: (T? value) {
|
||||
setState(() {
|
||||
_groupValue = _value;
|
||||
_groupValue = value;
|
||||
});
|
||||
widget.onChanged!(_value);
|
||||
widget.onChanged!(value);
|
||||
},
|
||||
),
|
||||
],
|
||||
@ -52,7 +51,7 @@ class _AMapRadioGroupState<T> extends State<AMapRadioGroup<T>> {
|
||||
|
||||
if (widget.radioValueMap != null) {
|
||||
widget.radioValueMap!.forEach((key, value) {
|
||||
radioList.add(_myRadio(key, value));
|
||||
radioList.add(myRadio(key, value));
|
||||
});
|
||||
}
|
||||
return Container(
|
||||
|
@ -1,14 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
typedef void OnChanged(bool value);
|
||||
typedef OnChanged = void Function(bool value);
|
||||
|
||||
class AMapSwitchButton extends StatefulWidget {
|
||||
const AMapSwitchButton({
|
||||
Key? key,
|
||||
super.key,
|
||||
this.label,
|
||||
this.onSwitchChanged,
|
||||
this.defaultValue = true,
|
||||
}) : super(key: key);
|
||||
});
|
||||
|
||||
final Text? label;
|
||||
final Function? onSwitchChanged;
|
||||
|
@ -3,7 +3,7 @@ description: Demonstrates how to use the amap_map plugin.
|
||||
|
||||
# The following line prevents the package from being accidentally published to
|
||||
# pub.dev using `pub publish`. This is preferred for private packages.
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
environment:
|
||||
sdk: ">=3.1.5 <4.0.0"
|
||||
@ -12,22 +12,12 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
permission_handler: ^11.3.0
|
||||
flutter_plugin_android_lifecycle: ^2.0.17
|
||||
permission_handler: ^11.3.1
|
||||
|
||||
amap_map:
|
||||
# When depending on this package from a real application you should use:
|
||||
# amap_map: ^x.y.z
|
||||
# See https://dart.dev/tools/pub/dependencies#version-constraints
|
||||
# The example app is bundled with the plugin so we use a path dependency on
|
||||
# the parent directory to use the current plugin's version.
|
||||
path: ../
|
||||
x_common: ^1.0.4
|
||||
|
||||
# amap_map_extensions: ^0.0.1
|
||||
# amap_map_extensions:
|
||||
# path: ../../amap_map_extensions
|
||||
|
||||
x_amap_base: ^1.0.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
@ -38,7 +28,6 @@ dev_dependencies:
|
||||
|
||||
# The following section is specific to Flutter.
|
||||
flutter:
|
||||
|
||||
# The following line ensures that the Material Icons font is
|
||||
# included with your application, so that you can use the icons in
|
||||
# the material Icons class.
|
||||
@ -50,5 +39,3 @@ flutter:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
|
||||
|
||||
|
@ -3,36 +3,36 @@ import 'package:x_amap_base/x_amap_base.dart';
|
||||
|
||||
void main() {
|
||||
test('Distance between two different point', () {
|
||||
LatLng p1 = LatLng(1, 1);
|
||||
LatLng p2 = LatLng(2, 2);
|
||||
LatLng p1 = const LatLng(1, 1);
|
||||
LatLng p2 = const LatLng(2, 2);
|
||||
double distance = AMapTools.distanceBetween(p1, p2);
|
||||
expect(distance, 157401.56104583555);
|
||||
});
|
||||
|
||||
test('Distance between two same point', () {
|
||||
LatLng p1 = LatLng(1, 1);
|
||||
LatLng p2 = LatLng(1, 1);
|
||||
LatLng p1 = const LatLng(1, 1);
|
||||
LatLng p2 = const LatLng(1, 1);
|
||||
double distance = AMapTools.distanceBetween(p1, p2);
|
||||
expect(distance, 0);
|
||||
});
|
||||
|
||||
test('Distance between two different point with equal lat', () {
|
||||
LatLng p1 = LatLng(1, 1);
|
||||
LatLng p2 = LatLng(1, 2);
|
||||
LatLng p1 = const LatLng(1, 1);
|
||||
LatLng p2 = const LatLng(1, 2);
|
||||
double distance = AMapTools.distanceBetween(p1, p2);
|
||||
expect(distance, 111302.53586533663);
|
||||
});
|
||||
|
||||
test('Distance between two different point with equal lng', () {
|
||||
LatLng p1 = LatLng(1, 1);
|
||||
LatLng p2 = LatLng(2, 1);
|
||||
LatLng p1 = const LatLng(1, 1);
|
||||
LatLng p2 = const LatLng(2, 1);
|
||||
double distance = AMapTools.distanceBetween(p1, p2);
|
||||
expect(distance, 111319.49079327357);
|
||||
});
|
||||
|
||||
test('Distance between two different point with close point', () {
|
||||
LatLng p1 = LatLng(39.938212, 116.455139);
|
||||
LatLng p2 = LatLng(39.987656, 116.265605);
|
||||
LatLng p1 = const LatLng(39.938212, 116.455139);
|
||||
LatLng p2 = const LatLng(39.987656, 116.265605);
|
||||
double distance = AMapTools.distanceBetween(p1, p2);
|
||||
expect(distance, 17082.425889709597);
|
||||
});
|
||||
|
@ -262,6 +262,15 @@
|
||||
|
||||
// 设置logo的位置
|
||||
self.logoCenter = logoCenter;
|
||||
|
||||
// 设置地图语言
|
||||
NSString *mapLanguage = dict[@"mapLanguage"];
|
||||
// 中文:@0: 英文:@1. 英文使用注意事项:1、不能和自定义地图样式同时使用;2、英文状态只在MAMapTypeStandard生效
|
||||
if ([mapLanguage isEqualToString:@"zh_cn"]) {
|
||||
self.mapLanguage = @0;
|
||||
} else if ([mapLanguage isEqualToString:@"en"]) {
|
||||
self.mapLanguage = @1;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -11,7 +11,7 @@
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
/// 高德地图Flutter插件入口文件
|
||||
library amap_map;
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
@ -24,12 +24,10 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:x_common/utils/logger.dart';
|
||||
|
||||
export 'package:amap_map/src/types/types.dart';
|
||||
|
||||
part 'src/amap_initializer.dart';
|
||||
part 'src/amap_controller.dart';
|
||||
part 'src/amap_widget.dart';
|
||||
part 'src/amap_loader.dart';
|
||||
part 'src/utils/location_utils.dart';
|
||||
|
@ -10,7 +10,7 @@
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
part of amap_map;
|
||||
part of '../amap_map.dart';
|
||||
|
||||
final MethodChannelAMapFlutterMap _methodChannel =
|
||||
AMapFlutterPlatform.instance as MethodChannelAMapFlutterMap;
|
||||
@ -30,7 +30,7 @@ class AMapController {
|
||||
static Future<AMapController> init(
|
||||
int id,
|
||||
CameraPosition initialCameration,
|
||||
_MapState mapState,
|
||||
mapState,
|
||||
) async {
|
||||
await _methodChannel.init(id);
|
||||
return AMapController._(
|
||||
@ -55,48 +55,42 @@ class AMapController {
|
||||
_methodChannel
|
||||
.onCameraMove(mapId: mapId)
|
||||
.listen((CameraPositionMoveEvent e) {
|
||||
_mapState._extensions.values.forEach((ext) => ext.onCameraMove(e.value));
|
||||
_mapState.widget.onCameraMove?.call(e.value);
|
||||
if (_mapState.widget.infoWindowAdapter != null) {
|
||||
_mapState.updateMarkers();
|
||||
}
|
||||
});
|
||||
|
||||
_methodChannel
|
||||
.onCameraMoveEnd(mapId: mapId)
|
||||
.listen((CameraPositionMoveEndEvent e) {
|
||||
_mapState._extensions.values
|
||||
.forEach((ext) => ext.onCameraMoveEnd(e.value));
|
||||
_mapState.widget.onCameraMoveEnd?.call(e.value);
|
||||
});
|
||||
_methodChannel
|
||||
.onMapTap(mapId: mapId)
|
||||
.listen(((MapTapEvent e) => _mapState.widget.onTap?.call(e.value)));
|
||||
_methodChannel.onMapLongPress(mapId: mapId).listen(((MapLongPressEvent e) {
|
||||
_mapState._extensions.values.forEach((ext) => ext.onLongPress(e.value));
|
||||
_mapState.widget.onLongPress?.call(e.value);
|
||||
}));
|
||||
|
||||
_methodChannel.onPoiTouched(mapId: mapId).listen(((MapPoiTouchEvent e) {
|
||||
_mapState._extensions.values.forEach((ext) => ext.onPoiTouched(e.value));
|
||||
_mapState.widget.onPoiTouched?.call(e.value);
|
||||
}));
|
||||
|
||||
_methodChannel.onMarkerTap(mapId: mapId).listen((MarkerTapEvent e) {
|
||||
_mapState._extensions.values.forEach((ext) => ext.onMarkerTap(e.value));
|
||||
_mapState.onMarkerTap(e.value);
|
||||
});
|
||||
|
||||
_methodChannel.onMarkerDragEnd(mapId: mapId).listen((MarkerDragEndEvent e) {
|
||||
_mapState._extensions.values
|
||||
.forEach((ext) => ext.onMarkerDragEnd(e.value));
|
||||
_mapState.onMarkerDragEnd(e.value, e.position);
|
||||
});
|
||||
|
||||
_methodChannel.onPolylineTap(mapId: mapId).listen((PolylineTapEvent e) {
|
||||
_mapState._extensions.values.forEach((ext) => ext.onPolylineTap(e.value));
|
||||
_mapState.onPolylineTap(e.value);
|
||||
});
|
||||
}
|
||||
|
||||
void disponse() {
|
||||
void dispose() {
|
||||
_methodChannel.dispose(id: mapId);
|
||||
}
|
||||
|
||||
@ -150,4 +144,12 @@ class AMapController {
|
||||
Future<LatLng> fromScreenCoordinate(ScreenCoordinate screenCoordinate) {
|
||||
return _methodChannel.fromScreenLocation(screenCoordinate, mapId: mapId);
|
||||
}
|
||||
|
||||
Future<String> getMapContentApprovalNumber() {
|
||||
return _methodChannel.getMapContentApprovalNumber(mapId: mapId);
|
||||
}
|
||||
|
||||
Future<String> getSatelliteImageApprovalNumber() {
|
||||
return _methodChannel.getSatelliteImageApprovalNumber(mapId: mapId);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
part of amap_map;
|
||||
part of '../amap_map.dart';
|
||||
|
||||
class AMapInitializer {
|
||||
static AMapApiKey? _apiKey;
|
||||
|
@ -1,94 +0,0 @@
|
||||
// Copyright 2023-2024 kuloud
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
part of amap_map;
|
||||
|
||||
/// 加载器,在[AMapWidget]的生命周期上绑定拓展
|
||||
class AMapLoader extends StatefulWidget {
|
||||
const AMapLoader(
|
||||
{super.key, required this.mapView, required this.extensions});
|
||||
|
||||
final Widget mapView;
|
||||
final List<AMapExtension> extensions;
|
||||
|
||||
@override
|
||||
State<AMapLoader> createState() => _AMapLoaderState();
|
||||
|
||||
static void prepare() {
|
||||
// TODO Loader 初始化静态方法,在initState时做些逻辑
|
||||
}
|
||||
|
||||
/// 传递构建视图,拓展按需进行包装和挂载定制视图
|
||||
Widget buildFromExtension(AMapContext aMapContext) {
|
||||
Widget child = mapView;
|
||||
for (var e in extensions) {
|
||||
child = e.build(aMapContext, child);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/// [didChangeDependencies] 状态更新时,挨个遍历进行拓展的更新操作
|
||||
void prepareFromExtension(AMapContext aMapContext) {
|
||||
for (var e in extensions) {
|
||||
e.prepare(aMapContext);
|
||||
}
|
||||
}
|
||||
|
||||
/// [didChangeDependencies] 状态更新时,挨个遍历进行拓展的更新操作
|
||||
void updateFromExtension(AMapContext aMapContext) {
|
||||
for (var e in extensions) {
|
||||
e.update(aMapContext);
|
||||
}
|
||||
// Future.forEach(extensions, (ext) => ext.update(aMapContext));
|
||||
}
|
||||
}
|
||||
|
||||
class _AMapLoaderState extends State<AMapLoader> {
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
final aMapContext = AMapContext(
|
||||
buildContext: context,
|
||||
currentStep: CurrentStep.preparing,
|
||||
loader: widget);
|
||||
|
||||
widget.prepareFromExtension(aMapContext);
|
||||
super.didChangeDependencies();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant AMapLoader oldWidget) {
|
||||
final aMapContext = AMapContext(
|
||||
buildContext: context,
|
||||
currentStep: CurrentStep.updating,
|
||||
loader: widget);
|
||||
widget.updateFromExtension(aMapContext);
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
for (var e in widget.extensions) {
|
||||
e.onDispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Set the extension context for this node.
|
||||
final aMapContext = AMapContext(
|
||||
buildContext: context,
|
||||
currentStep: CurrentStep.building,
|
||||
loader: widget);
|
||||
|
||||
return widget.buildFromExtension(aMapContext);
|
||||
}
|
||||
}
|
@ -10,9 +10,9 @@
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
part of amap_map;
|
||||
part of '../amap_map.dart';
|
||||
|
||||
typedef void MapCreatedCallback(AMapController controller);
|
||||
typedef MapCreatedCallback = void Function(AMapController controller);
|
||||
|
||||
///用于展示高德地图的Widget
|
||||
class AMapWidget extends StatefulWidget {
|
||||
@ -106,7 +106,11 @@ class AMapWidget extends StatefulWidget {
|
||||
///需要应用到地图上的手势集合
|
||||
final Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers;
|
||||
|
||||
final List<AMapExtension> extensions;
|
||||
/// 设置地图语言
|
||||
final MapLanguage? mapLanguage;
|
||||
|
||||
/// Marker InfoWindow 适配器
|
||||
final InfoWindowAdapter? infoWindowAdapter;
|
||||
|
||||
/// 创建一个展示高德地图的widget
|
||||
///
|
||||
@ -120,7 +124,7 @@ class AMapWidget extends StatefulWidget {
|
||||
///
|
||||
/// [AssertionError] will be thrown if [initialCameraPosition] is null;
|
||||
const AMapWidget(
|
||||
{Key? key,
|
||||
{super.key,
|
||||
this.initialCameraPosition =
|
||||
const CameraPosition(target: LatLng(39.909187, 116.397451), zoom: 10),
|
||||
this.mapType = MapType.normal,
|
||||
@ -149,11 +153,11 @@ class AMapWidget extends StatefulWidget {
|
||||
this.markers = const <Marker>{},
|
||||
this.polylines = const <Polyline>{},
|
||||
this.polygons = const <Polygon>{},
|
||||
this.extensions = const [],
|
||||
this.mapLanguage,
|
||||
this.infoWindowAdapter,
|
||||
this.logoPosition,
|
||||
this.logoBottomMargin,
|
||||
this.logoLeftMargin})
|
||||
: super(key: key);
|
||||
this.logoLeftMargin});
|
||||
|
||||
///
|
||||
@override
|
||||
@ -164,7 +168,7 @@ class _MapState extends State<AMapWidget> {
|
||||
Map<String, Marker> _markers = <String, Marker>{};
|
||||
Map<String, Polyline> _polylines = <String, Polyline>{};
|
||||
Map<String, Polygon> _polygons = <String, Polygon>{};
|
||||
Map<String, AMapExtension> _extensions = <String, AMapExtension>{};
|
||||
final Map<String, Widget?> _infoWindows = <String, Widget?>{};
|
||||
|
||||
final Completer<AMapController> _controller = Completer<AMapController>();
|
||||
late _AMapOptions _mapOptions;
|
||||
@ -186,22 +190,19 @@ class _MapState extends State<AMapWidget> {
|
||||
onPlatformViewCreated,
|
||||
);
|
||||
|
||||
return AMapLoader(
|
||||
mapView: mapView,
|
||||
extensions: widget.extensions,
|
||||
return Stack(
|
||||
children: [mapView, ..._infoWindows.values.nonNulls],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
AMapLoader.prepare();
|
||||
super.initState();
|
||||
_mapOptions = _AMapOptions.fromWidget(widget);
|
||||
_markers = keyByMarkerId(widget.markers);
|
||||
_polygons = keyByPolygonId(widget.polygons);
|
||||
_polylines = keyByPolylineId(widget.polylines);
|
||||
|
||||
_extensions = keyByExtensionId(widget.extensions);
|
||||
print('initState AMapWidget');
|
||||
}
|
||||
|
||||
@ -209,7 +210,7 @@ class _MapState extends State<AMapWidget> {
|
||||
void dispose() async {
|
||||
super.dispose();
|
||||
AMapController controller = await _controller.future;
|
||||
controller.disponse();
|
||||
controller.dispose();
|
||||
print('dispose AMapWidget with mapId: ${controller.mapId}');
|
||||
}
|
||||
|
||||
@ -222,17 +223,16 @@ class _MapState extends State<AMapWidget> {
|
||||
@override
|
||||
void deactivate() async {
|
||||
super.deactivate();
|
||||
print('deactivate AMapWidget}');
|
||||
print('deactivate AMapWidget');
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant AMapWidget oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
_updateOptions();
|
||||
_updateMarkers();
|
||||
updateMarkers();
|
||||
_updatePolylines();
|
||||
_updatePolygons();
|
||||
_updateExtensions();
|
||||
}
|
||||
|
||||
Future<void> onPlatformViewCreated(int id) async {
|
||||
@ -243,46 +243,38 @@ class _MapState extends State<AMapWidget> {
|
||||
);
|
||||
_controller.complete(controller);
|
||||
|
||||
if (_extensions.isNotEmpty) {
|
||||
debugPrint('[onPlatformViewCreated] $controller');
|
||||
await Future.forEach(_extensions.values, (e) {
|
||||
e.bindMethodChannel(controller.channel);
|
||||
e.bindMapController(controller);
|
||||
});
|
||||
}
|
||||
|
||||
final MapCreatedCallback? _onMapCreated = widget.onMapCreated;
|
||||
if (_onMapCreated != null) {
|
||||
_onMapCreated(controller);
|
||||
final MapCreatedCallback? onMapCreated = widget.onMapCreated;
|
||||
if (onMapCreated != null) {
|
||||
onMapCreated(controller);
|
||||
}
|
||||
}
|
||||
|
||||
void onMarkerTap(String markerId) {
|
||||
final Marker? _marker = _markers[markerId];
|
||||
if (_marker != null) {
|
||||
final ArgumentCallback<String>? _onTap = _marker.onTap;
|
||||
if (_onTap != null) {
|
||||
_onTap(markerId);
|
||||
final Marker? marker = _markers[markerId];
|
||||
if (marker != null) {
|
||||
final ArgumentCallback<String>? onTap = marker.onTap;
|
||||
if (onTap != null) {
|
||||
onTap(markerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onMarkerDragEnd(String markerId, LatLng position) {
|
||||
final Marker? _marker = _markers[markerId];
|
||||
if (_marker != null) {
|
||||
final MarkerDragEndCallback? _onDragEnd = _marker.onDragEnd;
|
||||
if (_onDragEnd != null) {
|
||||
_onDragEnd(markerId, position);
|
||||
final Marker? marker = _markers[markerId];
|
||||
if (marker != null) {
|
||||
final MarkerDragEndCallback? onDragEnd = marker.onDragEnd;
|
||||
if (onDragEnd != null) {
|
||||
onDragEnd(markerId, position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onPolylineTap(String polylineId) {
|
||||
final Polyline? _polyline = _polylines[polylineId];
|
||||
if (_polyline != null) {
|
||||
final ArgumentCallback<String>? _onTap = _polyline.onTap;
|
||||
if (_onTap != null) {
|
||||
_onTap(polylineId);
|
||||
final Polyline? polyline = _polylines[polylineId];
|
||||
if (polyline != null) {
|
||||
final ArgumentCallback<String>? onTap = polyline.onTap;
|
||||
if (onTap != null) {
|
||||
onTap(polylineId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -299,12 +291,24 @@ class _MapState extends State<AMapWidget> {
|
||||
_mapOptions = newOptions;
|
||||
}
|
||||
|
||||
void _updateMarkers() async {
|
||||
void updateMarkers() async {
|
||||
final AMapController controller = await _controller.future;
|
||||
MarkerUpdates markerUpdates =
|
||||
MarkerUpdates.from(_markers.values.toSet(), widget.markers);
|
||||
|
||||
markerUpdates.markerIdsToRemove?.forEach((markerId) {
|
||||
_removeInfoWindow(markerId);
|
||||
});
|
||||
|
||||
// ignore: unawaited_futures
|
||||
controller._updateMarkers(
|
||||
MarkerUpdates.from(_markers.values.toSet(), widget.markers));
|
||||
controller._updateMarkers(markerUpdates);
|
||||
_markers = keyByMarkerId(widget.markers);
|
||||
|
||||
if (widget.infoWindowAdapter != null) {
|
||||
for (var marker in _markers.values) {
|
||||
_onInfoWindowUpdate(marker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _updatePolylines() async {
|
||||
@ -321,9 +325,19 @@ class _MapState extends State<AMapWidget> {
|
||||
_polygons = keyByPolygonId(widget.polygons);
|
||||
}
|
||||
|
||||
void _updateExtensions() async {
|
||||
// final AMapController controller = await _controller.future;
|
||||
_extensions = keyByExtensionId(widget.extensions);
|
||||
void _onInfoWindowUpdate(Marker marker) {
|
||||
if (widget.infoWindowAdapter != null) {
|
||||
setState(() {
|
||||
_infoWindows[marker.id] =
|
||||
widget.infoWindowAdapter!.getInfoWindow(context, marker);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _removeInfoWindow(String markerId) {
|
||||
setState(() {
|
||||
_infoWindows.remove(markerId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,8 +394,10 @@ class _AMapOptions {
|
||||
final int? logoBottomMargin;
|
||||
final int? logoLeftMargin;
|
||||
|
||||
_AMapOptions({
|
||||
this.mapType = MapType.normal,
|
||||
final MapLanguage? mapLanguage;
|
||||
|
||||
_AMapOptions(
|
||||
{this.mapType = MapType.normal,
|
||||
this.buildingsEnabled,
|
||||
this.customStyleOptions,
|
||||
this.myLocationStyleOptions,
|
||||
@ -399,7 +415,7 @@ class _AMapOptions {
|
||||
this.logoPosition,
|
||||
this.logoBottomMargin,
|
||||
this.logoLeftMargin,
|
||||
});
|
||||
this.mapLanguage});
|
||||
|
||||
static _AMapOptions fromWidget(AMapWidget map) {
|
||||
return _AMapOptions(
|
||||
@ -420,7 +436,9 @@ class _AMapOptions {
|
||||
myLocationStyleOptions: map.myLocationStyleOptions?.clone(),
|
||||
logoPosition: map.logoPosition?.index,
|
||||
logoBottomMargin: map.logoBottomMargin,
|
||||
logoLeftMargin: map.logoLeftMargin);
|
||||
logoLeftMargin: map.logoLeftMargin,
|
||||
mapLanguage: map.mapLanguage,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
@ -449,6 +467,7 @@ class _AMapOptions {
|
||||
addIfNonNull('logoPosition', logoPosition);
|
||||
addIfNonNull('logoBottomMargin', logoBottomMargin);
|
||||
addIfNonNull('logoLeftMargin', logoLeftMargin);
|
||||
addIfNonNull('mapLanguage', mapLanguage?.value);
|
||||
return optionsMap;
|
||||
}
|
||||
|
||||
|
@ -18,29 +18,27 @@ class MapEvent<T> {
|
||||
|
||||
///定位回调接口
|
||||
class LocationChangedEvent extends MapEvent<AMapLocation> {
|
||||
LocationChangedEvent(int mapId, AMapLocation value) : super(mapId, value);
|
||||
LocationChangedEvent(super.mapId, super.value);
|
||||
}
|
||||
|
||||
///地图移动回调
|
||||
class CameraPositionMoveEvent extends MapEvent<CameraPosition> {
|
||||
CameraPositionMoveEvent(int mapId, CameraPosition value)
|
||||
: super(mapId, value);
|
||||
CameraPositionMoveEvent(super.mapId, super.value);
|
||||
}
|
||||
|
||||
///地图移动结束回调
|
||||
class CameraPositionMoveEndEvent extends MapEvent<CameraPosition> {
|
||||
CameraPositionMoveEndEvent(int mapId, CameraPosition value)
|
||||
: super(mapId, value);
|
||||
CameraPositionMoveEndEvent(super.mapId, super.value);
|
||||
}
|
||||
|
||||
///点击地图回调
|
||||
class MapTapEvent extends MapEvent<LatLng> {
|
||||
MapTapEvent(int mapId, LatLng value) : super(mapId, value);
|
||||
MapTapEvent(super.mapId, super.value);
|
||||
}
|
||||
|
||||
///长按地图回调
|
||||
class MapLongPressEvent extends MapEvent<LatLng> {
|
||||
MapLongPressEvent(int mapId, LatLng value) : super(mapId, value);
|
||||
MapLongPressEvent(super.mapId, super.value);
|
||||
}
|
||||
|
||||
/// 带位置回调的地图事件
|
||||
@ -57,21 +55,20 @@ class _PositionedMapEvent<T> extends MapEvent<T> {
|
||||
|
||||
/// [Marker] 的点击事件
|
||||
class MarkerTapEvent extends MapEvent<String> {
|
||||
MarkerTapEvent(int mapId, String markerId) : super(mapId, markerId);
|
||||
MarkerTapEvent(super.mapId, super.markerId);
|
||||
}
|
||||
|
||||
/// [Marker] 的拖拽结束事件,附带拖拽结束时的位置信息[LatLng].
|
||||
class MarkerDragEndEvent extends _PositionedMapEvent<String> {
|
||||
MarkerDragEndEvent(int mapId, LatLng position, String markerId)
|
||||
: super(mapId, position, markerId);
|
||||
MarkerDragEndEvent(super.mapId, super.position, super.markerId);
|
||||
}
|
||||
|
||||
/// [Polyline] 的点击事件
|
||||
class PolylineTapEvent extends MapEvent<String> {
|
||||
PolylineTapEvent(int mapId, String polylineId) : super(mapId, polylineId);
|
||||
PolylineTapEvent(super.mapId, super.polylineId);
|
||||
}
|
||||
|
||||
/// Poi点击事件
|
||||
class MapPoiTouchEvent extends MapEvent<AMapPoi> {
|
||||
MapPoiTouchEvent(int mapId, AMapPoi poi) : super(mapId, poi);
|
||||
MapPoiTouchEvent(super.mapId, super.poi);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import 'package:stream_transform/stream_transform.dart';
|
||||
|
||||
import 'map_event.dart';
|
||||
|
||||
// ignore: constant_identifier_names
|
||||
const VIEW_TYPE = 'com.amap.flutter.map';
|
||||
|
||||
/// 使用[MethodChannel]与Native代码通信的[AMapFlutterPlatform]的实现。
|
||||
@ -182,7 +183,7 @@ class MethodChannelAMapFlutterMap implements AMapFlutterPlatform {
|
||||
_mapEventStreamController.add(LocationChangedEvent(
|
||||
mapId, AMapLocation.fromMap(call.arguments['location'])!));
|
||||
} catch (e) {
|
||||
print("location#changed error=======>" + e.toString());
|
||||
print("location#changed error=======>$e");
|
||||
}
|
||||
break;
|
||||
|
||||
@ -191,7 +192,7 @@ class MethodChannelAMapFlutterMap implements AMapFlutterPlatform {
|
||||
_mapEventStreamController.add(CameraPositionMoveEvent(
|
||||
mapId, CameraPosition.fromMap(call.arguments['position'])!));
|
||||
} catch (e) {
|
||||
print("camera#onMove error===>" + e.toString());
|
||||
print("camera#onMove error===>$e");
|
||||
}
|
||||
break;
|
||||
case 'camera#onMoveEnd':
|
||||
@ -199,7 +200,7 @@ class MethodChannelAMapFlutterMap implements AMapFlutterPlatform {
|
||||
_mapEventStreamController.add(CameraPositionMoveEndEvent(
|
||||
mapId, CameraPosition.fromMap(call.arguments['position'])!));
|
||||
} catch (e) {
|
||||
print("camera#onMoveEnd error===>" + e.toString());
|
||||
print("camera#onMoveEnd error===>$e");
|
||||
}
|
||||
break;
|
||||
case 'map#onTap':
|
||||
@ -232,7 +233,7 @@ class MethodChannelAMapFlutterMap implements AMapFlutterPlatform {
|
||||
_mapEventStreamController.add(MapPoiTouchEvent(
|
||||
mapId, AMapPoi.fromJson(call.arguments['poi'])!));
|
||||
} catch (e) {
|
||||
print('map#onPoiTouched error===>' + e.toString());
|
||||
print('map#onPoiTouched error===>$e');
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -284,4 +285,20 @@ class MethodChannelAMapFlutterMap implements AMapFlutterPlatform {
|
||||
'map#fromScreenCoordinate', screenCoordinate.toJson());
|
||||
return LatLng(latLng![0] as double, latLng[1] as double);
|
||||
}
|
||||
|
||||
Future<String> getMapContentApprovalNumber({
|
||||
required int mapId,
|
||||
}) async {
|
||||
return await channel(mapId)
|
||||
.invokeMethod<String>('map#contentApprovalNumber') ??
|
||||
'';
|
||||
}
|
||||
|
||||
Future<String> getSatelliteImageApprovalNumber({
|
||||
required int mapId,
|
||||
}) async {
|
||||
return await channel(mapId)
|
||||
.invokeMethod<String>('map#satelliteImageApprovalNumber') ??
|
||||
'';
|
||||
}
|
||||
}
|
||||
|
@ -1,135 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
|
||||
/// [amap_map]插件支持默认的[InfoWindow]展示[title]和[snippet]字段,如果要自定义
|
||||
/// [InfoWindow],需要集成此内置插件。
|
||||
///
|
||||
/// ```dart
|
||||
/// AMapWidget map = AMapWidget(
|
||||
/// onMapCreated: _onMapCreated,
|
||||
/// markers: Set<Marker>.of(_markers.values),
|
||||
/// extensions: [
|
||||
/// InfoWindowExtension(
|
||||
/// infoWindow: Container(
|
||||
/// child: Text('Custom widget'),
|
||||
/// ))
|
||||
/// ],
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// 此插件会在[AMapWidget]外侧套一层[Stack],根据屏幕坐标和经纬度进行适配自定义视图
|
||||
///
|
||||
/// ```dart
|
||||
/// Stack(
|
||||
/// children: [
|
||||
/// child,
|
||||
/// Positioned(
|
||||
/// top: 0,
|
||||
/// left: 0,
|
||||
/// child: Visibility(child: infoWindow),
|
||||
/// ),
|
||||
/// ],
|
||||
/// )
|
||||
/// ```
|
||||
class InfoWindowExtension extends AMapExtension {
|
||||
InfoWindowExtension({required this.infoWindow, this.option});
|
||||
|
||||
final _streamController = StreamController<InfoWindowExtension>.broadcast();
|
||||
|
||||
final Widget infoWindow;
|
||||
InfoWindowOption? option;
|
||||
|
||||
final GlobalKey _infoWindowKey = GlobalKey();
|
||||
|
||||
AMapController? mapController;
|
||||
double? _x;
|
||||
double? _y;
|
||||
|
||||
@override
|
||||
void update(AMapContext aMapContext) {
|
||||
_update();
|
||||
}
|
||||
|
||||
@override
|
||||
onCameraMove(CameraPosition value) {
|
||||
_update();
|
||||
}
|
||||
|
||||
_update() async {
|
||||
if (mapController == null || option?.latLng == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final coordinate = await mapController!.toScreenCoordinate(option!.latLng!);
|
||||
|
||||
_x = coordinate.x.toDouble();
|
||||
_y = coordinate.y.toDouble();
|
||||
|
||||
final size = _infoWindowKey.currentContext?.size;
|
||||
if (size != null && _x != null && _y != null) {
|
||||
_x = _x! - size.width / 2;
|
||||
_y = _y! - size.height;
|
||||
}
|
||||
|
||||
_streamController.add(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bindMapController(AMapController controller) {
|
||||
debugPrint('[InfoWindowExtension] bindMapController: $controller');
|
||||
mapController = controller;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(AMapContext aMapContext, Widget child) {
|
||||
return Stack(
|
||||
key: ValueKey(this),
|
||||
children: [
|
||||
child,
|
||||
StreamBuilder<InfoWindowExtension>(
|
||||
initialData: this,
|
||||
stream: _streamController.stream,
|
||||
builder: (context, snapshot) {
|
||||
final data = snapshot.data;
|
||||
if (data == null ||
|
||||
!(data.option?.show ?? false) ||
|
||||
data._x == null) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
return Positioned(
|
||||
top: data._y,
|
||||
left: data._x,
|
||||
child: Container(
|
||||
key: _infoWindowKey,
|
||||
margin: data.option?.offset,
|
||||
child: infoWindow,
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onDispose() {
|
||||
_streamController.close();
|
||||
super.onDispose();
|
||||
}
|
||||
}
|
||||
|
||||
class InfoWindowOption {
|
||||
bool show = false;
|
||||
LatLng? latLng;
|
||||
EdgeInsetsGeometry? offset;
|
||||
|
||||
InfoWindowOption({this.show = false, this.latLng, this.offset});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'InfoWindowOption{show: $show, latLng: $latLng, offset: $offset}';
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export 'buildin/info_window_extension.dart';
|
@ -1,81 +0,0 @@
|
||||
// Copyright 2023-2024 kuloud
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
|
||||
/// 插件拓展,绑定[AMapWidget]的生命周期和控制器,实现基于地图的拓展能力(通常是地图交互的可
|
||||
/// 选功能)
|
||||
abstract class AMapExtension {
|
||||
late String _id;
|
||||
|
||||
String get id => _id;
|
||||
|
||||
AMapExtension() {
|
||||
this._id = this.hashCode.toString();
|
||||
}
|
||||
|
||||
/// 视图层级变化
|
||||
/// since v1.0.4
|
||||
void prepare(AMapContext aMapContext) {}
|
||||
|
||||
/// 视图变化
|
||||
/// since v1.0.4
|
||||
void update(AMapContext aMapContext) {}
|
||||
|
||||
void onDispose() {}
|
||||
|
||||
@Deprecated('使用 bindMapController ,计划在1.0.6移除')
|
||||
bindMethodChannel(MethodChannel channel) {}
|
||||
|
||||
/// 注入[AMapController] 方便地图交互
|
||||
bindMapController(AMapController controller) {}
|
||||
|
||||
Widget build(AMapContext aMapContext, Widget child) {
|
||||
/// 默认传递[AMapWidget],有部分场景需要在[AMapWidget]外包装容器,根据传递拓展列表顺序
|
||||
/// 链式执行
|
||||
return child;
|
||||
}
|
||||
|
||||
/// since v1.0.4
|
||||
onCameraMove(CameraPosition cameraPosition) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onCameraMoveEnd(CameraPosition cameraPosition) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onLongPress(LatLng latLng) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onPoiTouched(AMapPoi poi) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onMarkerTap(String value) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onMarkerDragEnd(String value) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onPolylineTap(String value) {}
|
||||
}
|
||||
|
||||
Map<String, AMapExtension> keyByExtensionId(
|
||||
Iterable<AMapExtension> extensions) {
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (extensions == null) {
|
||||
return <String, AMapExtension>{};
|
||||
}
|
||||
return Map<String, AMapExtension>.fromEntries(extensions.map(
|
||||
(AMapExtension extension) =>
|
||||
MapEntry<String, AMapExtension>(extension.id, extension)));
|
||||
}
|
@ -1,27 +1,42 @@
|
||||
/// 地图覆盖物基类
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class BaseOverlay {
|
||||
/// overlay id
|
||||
late String _id;
|
||||
String _id;
|
||||
|
||||
String get id => _id;
|
||||
|
||||
BaseOverlay() {
|
||||
this._id = this.hashCode.toString();
|
||||
// 初始化 _id,在创建对象时唯一确定
|
||||
BaseOverlay() : _id = _generateUniqueId();
|
||||
|
||||
// 设置复制的 ID,确保拷贝对象时的唯一性或保留性
|
||||
void setIdForCopy(String copyId) {
|
||||
if (copyId.isNotEmpty) {
|
||||
_id = copyId;
|
||||
} else {
|
||||
throw ArgumentError('Invalid ID for copy');
|
||||
}
|
||||
}
|
||||
|
||||
void setIdForCopy(String copyId) => _id = copyId;
|
||||
|
||||
// 克隆对象,确保子类正确实现 clone 方法
|
||||
BaseOverlay clone() {
|
||||
throw UnimplementedError(
|
||||
'BaseOverlay subClass should implement this methed.');
|
||||
'BaseOverlay subClass should implement this method.');
|
||||
}
|
||||
|
||||
// 将对象转换为 map 表示
|
||||
Map<String, dynamic> toMap() {
|
||||
throw UnimplementedError(
|
||||
'BaseOverlay subClass should implement this methed.');
|
||||
'BaseOverlay subClass should implement this method.');
|
||||
}
|
||||
|
||||
// 生成唯一 ID 的静态方法
|
||||
static String _generateUniqueId() {
|
||||
return '${DateTime.now().millisecondsSinceEpoch}_${UniqueKey()}';
|
||||
}
|
||||
}
|
||||
|
||||
// 序列化覆盖物集合
|
||||
List<Map<String, dynamic>>? serializeOverlaySet(Set<BaseOverlay> overlays) {
|
||||
return overlays
|
||||
.map<Map<String, dynamic>>((BaseOverlay overlay) => overlay.toMap())
|
||||
|
@ -38,7 +38,7 @@ class CameraPosition {
|
||||
///
|
||||
/// 主要在插件内部使用
|
||||
static CameraPosition? fromMap(dynamic json) {
|
||||
if (json == null || !(json is Map<dynamic, dynamic>)) {
|
||||
if (json == null || json is! Map<dynamic, dynamic>) {
|
||||
return null;
|
||||
}
|
||||
final LatLng? target = LatLng.fromJson(json['target']);
|
||||
|
@ -1,31 +0,0 @@
|
||||
// Copyright 2023-2024 kuloud
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 上下文
|
||||
class AMapContext {
|
||||
final BuildContext buildContext;
|
||||
final CurrentStep currentStep;
|
||||
final AMapLoader loader;
|
||||
|
||||
AMapContext(
|
||||
{required this.buildContext,
|
||||
required this.currentStep,
|
||||
required this.loader});
|
||||
}
|
||||
|
||||
enum CurrentStep {
|
||||
preparing,
|
||||
updating,
|
||||
building,
|
||||
}
|
37
lib/src/types/info_window_adapter.dart
Normal file
37
lib/src/types/info_window_adapter.dart
Normal file
@ -0,0 +1,37 @@
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
abstract class InfoWindowAdapter {
|
||||
Widget? getInfoWindow(BuildContext context, Marker marker);
|
||||
}
|
||||
|
||||
abstract class BaseInfoWindowAdapter implements InfoWindowAdapter {
|
||||
final AMapController? controller;
|
||||
|
||||
BaseInfoWindowAdapter(this.controller);
|
||||
|
||||
@override
|
||||
Widget? getInfoWindow(BuildContext context, Marker marker) {
|
||||
final contentView = buildInfoWindowContent(context, marker);
|
||||
return (contentView != null)
|
||||
? FutureBuilder(
|
||||
future: controller?.toScreenCoordinate(marker.position),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
double devicePixelRatio =
|
||||
MediaQuery.of(context).devicePixelRatio;
|
||||
return Positioned(
|
||||
left: snapshot.data!.x.toDouble() / devicePixelRatio,
|
||||
top: snapshot.data!.y.toDouble() / devicePixelRatio,
|
||||
child: contentView,
|
||||
);
|
||||
} else {
|
||||
return Container(); // 当未获取到数据时,返回空的 `Container`
|
||||
}
|
||||
},
|
||||
)
|
||||
: null;
|
||||
}
|
||||
|
||||
Widget? buildInfoWindowContent(BuildContext context, Marker marker);
|
||||
}
|
@ -8,7 +8,7 @@ import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'bitmap.dart';
|
||||
|
||||
/// Marker拖动回调
|
||||
typedef void MarkerDragEndCallback(String id, LatLng endPosition);
|
||||
typedef MarkerDragEndCallback = void Function(String id, LatLng endPosition);
|
||||
|
||||
///Marker的气泡
|
||||
///
|
||||
@ -91,17 +91,17 @@ class Marker extends BaseOverlay {
|
||||
this.zIndex = 0.0,
|
||||
this.onTap,
|
||||
this.onDragEnd,
|
||||
}) : this.alpha =
|
||||
}) : alpha =
|
||||
// ignore: unnecessary_null_comparison
|
||||
(alpha != null ? (alpha < 0 ? 0 : (alpha > 1 ? 1 : alpha)) : alpha),
|
||||
// ignore: unnecessary_null_comparison
|
||||
this.anchor = (anchor == null
|
||||
? Offset(0.5, 1.0)
|
||||
anchor = (anchor == null
|
||||
? const Offset(0.5, 1.0)
|
||||
: ((anchor.dx < 0 ||
|
||||
anchor.dx > 1 ||
|
||||
anchor.dy < 0 ||
|
||||
anchor.dy > 1)
|
||||
? Offset(0.5, 1.0)
|
||||
? const Offset(0.5, 1.0)
|
||||
: anchor)),
|
||||
super();
|
||||
|
||||
@ -182,6 +182,7 @@ class Marker extends BaseOverlay {
|
||||
return copyMark;
|
||||
}
|
||||
|
||||
@override
|
||||
Marker clone() => copyWith();
|
||||
|
||||
@override
|
||||
@ -233,9 +234,6 @@ class Marker extends BaseOverlay {
|
||||
zIndex == typedOther.zIndex;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => super.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Marker{id: $id, alpha: $alpha, anchor: $anchor, '
|
||||
@ -243,6 +241,22 @@ class Marker extends BaseOverlay {
|
||||
'icon: $icon, infoWindowEnable: $infoWindowEnable, infoWindow: $infoWindow, position: $position, rotation: $rotation, '
|
||||
'visible: $visible, zIndex: $zIndex, onTap: $onTap}';
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hashAll([
|
||||
id,
|
||||
alpha,
|
||||
anchor,
|
||||
clickable,
|
||||
draggable,
|
||||
icon,
|
||||
infoWindowEnable,
|
||||
infoWindow,
|
||||
position,
|
||||
rotation,
|
||||
visible,
|
||||
zIndex
|
||||
]);
|
||||
}
|
||||
|
||||
Map<String, Marker> keyByMarkerId(Iterable<Marker> markers) {
|
||||
|
@ -6,16 +6,6 @@ import 'types.dart';
|
||||
class MarkerUpdates {
|
||||
/// 根据之前的marker列表[previous]和当前的marker列表[current]创建[MakerUpdates].
|
||||
MarkerUpdates.from(Set<Marker> previous, Set<Marker> current) {
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (previous == null) {
|
||||
previous = Set<Marker>.identity();
|
||||
}
|
||||
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (current == null) {
|
||||
current = Set<Marker>.identity();
|
||||
}
|
||||
|
||||
final Map<String, Marker> previousMarkers = keyByMarkerId(previous);
|
||||
final Map<String, Marker> currentMarkers = keyByMarkerId(current);
|
||||
|
||||
@ -26,10 +16,10 @@ class MarkerUpdates {
|
||||
return currentMarkers[id]!;
|
||||
}
|
||||
|
||||
final Set<String> _markerIdsToRemove =
|
||||
final Set<String> tempMarkerIdsToRemove =
|
||||
prevMarkerIds.difference(currentMarkerIds);
|
||||
|
||||
final Set<Marker> _markersToAdd = currentMarkerIds
|
||||
final Set<Marker> tempMarkersToAdd = currentMarkerIds
|
||||
.difference(prevMarkerIds)
|
||||
.map(idToCurrentMarker)
|
||||
.toSet();
|
||||
@ -39,15 +29,15 @@ class MarkerUpdates {
|
||||
return current != previous;
|
||||
}
|
||||
|
||||
final Set<Marker> _markersToChange = currentMarkerIds
|
||||
final Set<Marker> tempMarkersToChange = currentMarkerIds
|
||||
.intersection(prevMarkerIds)
|
||||
.map(idToCurrentMarker)
|
||||
.where(hasChanged)
|
||||
.toSet();
|
||||
|
||||
markersToAdd = _markersToAdd;
|
||||
markerIdsToRemove = _markerIdsToRemove;
|
||||
markersToChange = _markersToChange;
|
||||
markersToAdd = tempMarkersToAdd;
|
||||
markerIdsToRemove = tempMarkerIdsToRemove;
|
||||
markersToChange = tempMarkersToChange;
|
||||
}
|
||||
|
||||
/// 想要添加的marker集合.
|
||||
|
@ -18,8 +18,8 @@ class Polygon extends BaseOverlay {
|
||||
this.fillColor = const Color(0xC487CEFA),
|
||||
this.visible = true,
|
||||
this.joinType = JoinType.bevel})
|
||||
: assert(points.length > 0),
|
||||
this.strokeWidth = (strokeWidth <= 0 ? 10 : strokeWidth),
|
||||
: assert(points.isNotEmpty),
|
||||
strokeWidth = (strokeWidth <= 0 ? 10 : strokeWidth),
|
||||
super();
|
||||
|
||||
/// 覆盖物的坐标点数组,不能为空
|
||||
@ -60,6 +60,7 @@ class Polygon extends BaseOverlay {
|
||||
return copyPolyline;
|
||||
}
|
||||
|
||||
@override
|
||||
Polygon clone() => copyWith();
|
||||
|
||||
/// 转换成可以序列化的map
|
||||
@ -76,8 +77,8 @@ class Polygon extends BaseOverlay {
|
||||
addIfPresent('id', id);
|
||||
json['points'] = _pointsToJson();
|
||||
addIfPresent('strokeWidth', strokeWidth);
|
||||
addIfPresent('strokeColor', strokeColor.value);
|
||||
addIfPresent('fillColor', fillColor.value);
|
||||
addIfPresent('strokeColor', strokeColor.toARGB32());
|
||||
addIfPresent('fillColor', fillColor.toARGB32());
|
||||
addIfPresent('visible', visible);
|
||||
addIfPresent('joinType', joinType.index);
|
||||
return json;
|
||||
@ -99,7 +100,8 @@ class Polygon extends BaseOverlay {
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => super.hashCode;
|
||||
int get hashCode => Object.hashAll(
|
||||
[id, points, strokeWidth, strokeColor, fillColor, visible, joinType]);
|
||||
|
||||
dynamic _pointsToJson() {
|
||||
final List<dynamic> result = <dynamic>[];
|
||||
|
@ -9,16 +9,6 @@ import 'types.dart';
|
||||
class PolygonUpdates {
|
||||
/// 通过Polygon的前后更新集合构造一个PolygonUpdates
|
||||
PolygonUpdates.from(Set<Polygon> previous, Set<Polygon> current) {
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (previous == null) {
|
||||
previous = Set<Polygon>.identity();
|
||||
}
|
||||
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (current == null) {
|
||||
current = Set<Polygon>.identity();
|
||||
}
|
||||
|
||||
final Map<String, Polygon> previousPolygons = keyByPolygonId(previous);
|
||||
final Map<String, Polygon> currentPolygons = keyByPolygonId(current);
|
||||
|
||||
@ -29,10 +19,10 @@ class PolygonUpdates {
|
||||
return currentPolygons[id]!;
|
||||
}
|
||||
|
||||
final Set<String> _polygonIdsToRemove =
|
||||
final Set<String> tempPolygonIdsToRemove =
|
||||
prevPolygonIds.difference(currentPolygonIds);
|
||||
|
||||
final Set<Polygon> _polygonsToAdd = currentPolygonIds
|
||||
final Set<Polygon> tempPolygonsToAdd = currentPolygonIds
|
||||
.difference(prevPolygonIds)
|
||||
.map(idToCurrentPolygon)
|
||||
.toSet();
|
||||
@ -42,15 +32,15 @@ class PolygonUpdates {
|
||||
return current != previous;
|
||||
}
|
||||
|
||||
final Set<Polygon> _polygonsToChange = currentPolygonIds
|
||||
final Set<Polygon> tempPolygonsToChange = currentPolygonIds
|
||||
.intersection(prevPolygonIds)
|
||||
.map(idToCurrentPolygon)
|
||||
.where(hasChanged)
|
||||
.toSet();
|
||||
|
||||
polygonsToAdd = _polygonsToAdd;
|
||||
polygonIdsToRemove = _polygonIdsToRemove;
|
||||
polygonsToChange = _polygonsToChange;
|
||||
polygonsToAdd = tempPolygonsToAdd;
|
||||
polygonIdsToRemove = tempPolygonIdsToRemove;
|
||||
polygonsToChange = tempPolygonsToChange;
|
||||
}
|
||||
|
||||
/// 想要添加的polygon对象集合.
|
||||
|
@ -62,9 +62,9 @@ class Polyline extends BaseOverlay {
|
||||
this.customTexture,
|
||||
this.onTap,
|
||||
this.color = const Color(0xCCC4E0F0),
|
||||
}) : assert(points.length > 0),
|
||||
this.width = (width <= 0 ? 10 : width),
|
||||
this.alpha = (alpha < 0 ? 0 : (alpha > 1 ? 1 : alpha)),
|
||||
}) : assert(points.isNotEmpty),
|
||||
width = (width <= 0 ? 10 : width),
|
||||
alpha = (alpha < 0 ? 0 : (alpha > 1 ? 1 : alpha)),
|
||||
super();
|
||||
|
||||
/// 覆盖物的坐标点数组,points不能为空
|
||||
@ -131,6 +131,7 @@ class Polyline extends BaseOverlay {
|
||||
return copyPolyline;
|
||||
}
|
||||
|
||||
@override
|
||||
Polyline clone() => copyWith();
|
||||
|
||||
/// 将对象转换为可序列化的map.
|
||||
@ -154,7 +155,7 @@ class Polyline extends BaseOverlay {
|
||||
addIfPresent('capType', capType.index);
|
||||
addIfPresent('joinType', joinType.index);
|
||||
addIfPresent('customTexture', customTexture?.toMap());
|
||||
addIfPresent('color', color.value);
|
||||
addIfPresent('color', color.toARGB32());
|
||||
return json;
|
||||
}
|
||||
|
||||
@ -176,9 +177,6 @@ class Polyline extends BaseOverlay {
|
||||
color == typedOther.color;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => super.hashCode;
|
||||
|
||||
dynamic _pointsToJson() {
|
||||
final List<dynamic> result = <dynamic>[];
|
||||
for (final LatLng point in points) {
|
||||
@ -186,6 +184,20 @@ class Polyline extends BaseOverlay {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hashAll([
|
||||
id,
|
||||
points,
|
||||
width,
|
||||
visible,
|
||||
geodesic,
|
||||
alpha,
|
||||
dashLineType,
|
||||
capType,
|
||||
joinType,
|
||||
color
|
||||
]);
|
||||
}
|
||||
|
||||
Map<String, Polyline> keyByPolylineId(Iterable<Polyline> polylines) {
|
||||
|
@ -10,16 +10,6 @@ import 'types.dart';
|
||||
class PolylineUpdates {
|
||||
/// 通过polyline的前后更新集合构造一个polylineUpdates
|
||||
PolylineUpdates.from(Set<Polyline> previous, Set<Polyline> current) {
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (previous == null) {
|
||||
previous = Set<Polyline>.identity();
|
||||
}
|
||||
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (current == null) {
|
||||
current = Set<Polyline>.identity();
|
||||
}
|
||||
|
||||
final Map<String, Polyline> previousPolylines = keyByPolylineId(previous);
|
||||
final Map<String, Polyline> currentPolylines = keyByPolylineId(current);
|
||||
|
||||
@ -30,10 +20,10 @@ class PolylineUpdates {
|
||||
return currentPolylines[id]!;
|
||||
}
|
||||
|
||||
final Set<String> _polylineIdsToRemove =
|
||||
final Set<String> tempPolylineIdsToRemove =
|
||||
prevPolylineIds.difference(currentPolylineIds);
|
||||
|
||||
final Set<Polyline> _polylinesToAdd = currentPolylineIds
|
||||
final Set<Polyline> tempPolylinesToAdd = currentPolylineIds
|
||||
.difference(prevPolylineIds)
|
||||
.map(idToCurrentPolyline)
|
||||
.toSet();
|
||||
@ -43,15 +33,15 @@ class PolylineUpdates {
|
||||
return current != previous;
|
||||
}
|
||||
|
||||
final Set<Polyline> _polylinesToChange = currentPolylineIds
|
||||
final Set<Polyline> tempPolylinesToChange = currentPolylineIds
|
||||
.intersection(prevPolylineIds)
|
||||
.map(idToCurrentPolyline)
|
||||
.where(hasChanged)
|
||||
.toSet();
|
||||
|
||||
polylinesToAdd = _polylinesToAdd;
|
||||
polylineIdsToRemove = _polylineIdsToRemove;
|
||||
polylinesToChange = _polylinesToChange;
|
||||
polylinesToAdd = tempPolylinesToAdd;
|
||||
polylineIdsToRemove = tempPolylineIdsToRemove;
|
||||
polylinesToChange = tempPolylinesToChange;
|
||||
}
|
||||
|
||||
/// 用于添加polyline的集合
|
||||
|
@ -20,8 +20,5 @@ export 'polyline_updates.dart';
|
||||
export 'polygon.dart';
|
||||
export 'polygon_updates.dart';
|
||||
export 'bitmap.dart';
|
||||
export 'extension_context.dart';
|
||||
export 'amap_extension.dart';
|
||||
export 'screen_coordinate.dart';
|
||||
|
||||
export '../extension/extensions.dart';
|
||||
export 'info_window_adapter.dart';
|
||||
|
@ -21,6 +21,15 @@ enum MapType {
|
||||
bus,
|
||||
}
|
||||
|
||||
/// 地图底图语言,目前支持中文底图和英文底图
|
||||
enum MapLanguage {
|
||||
chinese('zh_cn'),
|
||||
english('en');
|
||||
|
||||
final String value;
|
||||
const MapLanguage(this.value);
|
||||
}
|
||||
|
||||
// 设置摄像机的边界.
|
||||
class CameraTargetBounds {
|
||||
/// 使用指定的边界框或空值创建摄影机目标边界
|
||||
@ -63,12 +72,10 @@ class MinMaxZoomPreference {
|
||||
/// 缩放级别范围为[3, 20],超出范围取边界值
|
||||
///
|
||||
const MinMaxZoomPreference(double minZoom, double maxZoom)
|
||||
: this.minZoom =
|
||||
((minZoom < 3 ? 3 : minZoom) > (maxZoom > 20 ? 20 : maxZoom)
|
||||
: minZoom = ((minZoom < 3 ? 3 : minZoom) > (maxZoom > 20 ? 20 : maxZoom)
|
||||
? maxZoom
|
||||
: minZoom),
|
||||
this.maxZoom =
|
||||
((minZoom < 3 ? 3 : minZoom) > (maxZoom > 20 ? 20 : maxZoom)
|
||||
maxZoom = ((minZoom < 3 ? 3 : minZoom) > (maxZoom > 20 ? 20 : maxZoom)
|
||||
? minZoom
|
||||
: maxZoom);
|
||||
|
||||
@ -143,10 +150,10 @@ class MyLocationStyleOptions {
|
||||
}
|
||||
return MyLocationStyleOptions(
|
||||
json['enabled'] ?? false,
|
||||
circleFillColor: json['circleFillColor'] ?? null,
|
||||
circleStrokeColor: json['circleStrokeColor'] ?? null,
|
||||
circleStrokeWidth: json['circleStrokeWidth'] ?? null,
|
||||
icon: json['icon'] ?? null,
|
||||
circleFillColor: json['circleFillColor'],
|
||||
circleStrokeColor: json['circleStrokeColor'],
|
||||
circleStrokeWidth: json['circleStrokeWidth'],
|
||||
icon: json['icon'],
|
||||
);
|
||||
}
|
||||
|
||||
@ -160,8 +167,8 @@ class MyLocationStyleOptions {
|
||||
}
|
||||
|
||||
addIfPresent('enabled', enabled);
|
||||
addIfPresent('circleFillColor', circleFillColor?.value);
|
||||
addIfPresent('circleStrokeColor', circleStrokeColor?.value);
|
||||
addIfPresent('circleFillColor', circleFillColor?.toARGB32());
|
||||
addIfPresent('circleStrokeColor', circleStrokeColor?.toARGB32());
|
||||
addIfPresent('circleStrokeWidth', circleStrokeWidth);
|
||||
addIfPresent('icon', icon?.toMap());
|
||||
return json;
|
||||
@ -216,8 +223,8 @@ class CustomStyleOptions {
|
||||
}
|
||||
return CustomStyleOptions(
|
||||
json['enabled'] ?? false,
|
||||
styleData: json['styleData'] ?? null,
|
||||
styleExtraData: json['styleExtraData'] ?? null,
|
||||
styleData: json['styleData'],
|
||||
styleExtraData: json['styleExtraData'],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
part of amap_map;
|
||||
part of '../../amap_map.dart';
|
||||
|
||||
bool isLocationValid(AMapLocation location) {
|
||||
final LatLng latLng = location.latLng;
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: amap_map
|
||||
description: Amap SDK Flutter plugin for integrating AMapSDK in iOS and Android applications.
|
||||
version: 1.0.8
|
||||
version: 1.0.15
|
||||
homepage: https://github.com/kuloud/amap_map
|
||||
issue_tracker: https://github.com/kuloud/amap_map/issues
|
||||
platforms:
|
||||
@ -18,17 +18,15 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_plugin_android_lifecycle: ^2.0.17
|
||||
flutter_plugin_android_lifecycle: ^2.0.21
|
||||
plugin_platform_interface: ^2.1.8
|
||||
stream_transform: ^2.0.0
|
||||
|
||||
x_amap_base: ^1.0.3
|
||||
x_common: ^1.0.4
|
||||
# provider: ^6.1.1
|
||||
# x_amap_base:
|
||||
# path: ../x_amap_base
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^5.0.0
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
|
Reference in New Issue
Block a user