flutter_tencent_map 1.0.1
flutter_tencent_map: ^1.0.1 copied to clipboard
A Flutter plugin for Tencent Maps on Android and iOS, providing map display, overlays, camera control, location, and more with declarative API design.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_tencent_map/flutter_tencent_map.dart';
import 'pages/show_map_page.dart';
import 'pages/multi_map_page.dart';
import 'pages/multi_map_key_page.dart';
import 'pages/map_events_page.dart';
import 'pages/move_camera_page.dart';
import 'pages/map_query_page.dart';
import 'pages/map_lifecycle_page.dart';
import 'pages/android_view_mode_page.dart';
import 'pages/tc_d10_happy_path_page.dart';
import 'pages/tc_d11_missing_api_key_page.dart';
import 'pages/tc_d12_privacy_not_agreed_page.dart';
import 'pages/tc_d13_fake_key_page.dart';
import 'pages/tc_d14a_surface_view_page.dart';
import 'pages/tc_d14b_texture_view_page.dart';
import 'pages/tc_d15_map_config_page.dart';
import 'pages/tc_d16_ui_gestures_page.dart';
import 'pages/tc_d17_my_location_page.dart';
import 'pages/tc_d18_gesture_conflict_page.dart';
import 'pages/tc_d20_polygon_page.dart';
import 'pages/tc_d21_circle_page.dart';
import 'pages/tc_d22_bitmap_descriptor_page.dart';
import 'pages/tc_d23_polygon_texture_page.dart';
import 'pages/tc_d24_from_widget_page.dart';
import 'pages/tc_d30_arc_page.dart';
import 'pages/tc_d40_polyline_page.dart';
import 'pages/tc_d41_polyline_interaction_page.dart';
import 'pages/tc_d60_sdk_log_page.dart';
import 'pages/tc_d05b_batch_coordinate_page.dart';
import 'pages/tc_e50_marker_page.dart';
import 'pages/tc_e51_marker_collision_page.dart';
import 'pages/tc_e90_initial_overlay_push_page.dart';
import 'pages/tc_qa01_bounds_freeze_page.dart';
import 'pages/tc_qa02_polygon_hole_update_page.dart';
import 'pages/tc_qa03_marker_5k_anr_page.dart';
import 'pages/tc_qa04_polyline_segment_colors_page.dart';
import 'pages/tc_qa05_polyline_segment_styles_page.dart';
import 'pages/tc_qa06_polyline_points_seg_sync_page.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await TencentMapInitializer.setAgreePrivacy(true);
await TencentMapInitializer.start();
// // [可选] 开启插件层日志(观察 Channel/Compat/覆盖物链路,仅开发使用):
// // - 默认开启,方便开发期间通过 `adb logcat | grep FlutterTencentMap` (Android) 或
// // Xcode Console 搜索 `FlutterTencentMap` (iOS) 查看插件桥接层日志。
// // - Release 模式下自动静默(kReleaseMode 守卫),即使忘记移除也不影响生产包。
// await TencentMapInitializer.enableFlutterPluginLog();
// // [可选] 开启 SDK 日志(仅开发使用,正式发布请移除):
// await TencentMapInitializer.enableSdkLog(
// androidConfig: AndroidSdkLogConfig(
// // enable: false,
// level: TencentMapLogLevel.debug,
// toConsole: true,
// tags: ['TMS', 'TMCT', 'TNT', 'TDZ', 'DOWNLOADER'],
// ),
// iosConfig: IOSSdkLogConfig(
// level: TencentMapLogLevel.debug,
// toConsole: true,
// ),
// );
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Tencent Map Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const DemoListPage(),
);
}
}
class _DemoItem {
final String title;
final String subtitle;
final Widget Function() builder;
const _DemoItem({
required this.title,
required this.subtitle,
required this.builder,
});
}
class DemoListPage extends StatelessWidget {
const DemoListPage({Key? key}) : super(key: key);
static final _demos = <String, List<_DemoItem>>{
'基础功能': [
_DemoItem(
title: 'TC-D01: 基本地图显示',
subtitle: '地图渲染 + onMapCreated + onMapLoaded',
builder: () => const ShowMapPage(),
),
_DemoItem(
title: 'TC-D01.1: 地图多实例',
subtitle: '双地图独立操作 + 事件隔离 + MethodChannel 隔离',
builder: () => const MultiMapPage(),
),
_DemoItem(
title: 'TC-D01.2: 多地图 + 多 Key',
subtitle: '三地图:两独立 Key + 1 个无 Key(iOS SDK ≥ 6.13.0 per-instance)',
builder: () => const MultiMapKeyPage(),
),
_DemoItem(
title: 'TC-D02: 地图事件',
subtitle: 'Tap / LongPress / CameraMove / PoiTouched',
builder: () => const MapEventsPage(),
),
],
'1B 初始化场景': [
_DemoItem(
title: 'TC-D10: 完整配置',
subtitle: 'apiKey + TencentMapInitializer 已初始化,地图正常渲染(Happy Path)',
builder: () => const TcD10HappyPathPage(),
),
_DemoItem(
title: 'TC-D11: 缺失 apiKey',
subtitle: '不传 apiKey,fallback 到 AppDelegate / AndroidManifest',
builder: () => const TcD11MissingApiKeyPage(),
),
_DemoItem(
title: 'TC-D12: 隐私合规未同意',
subtitle: '默认 false 白屏;内置按钮切换为 true 验证反向生效',
builder: () => const TcD12PrivacyNotAgreedPage(),
),
_DemoItem(
title: 'TC-D13: 双端错误 Key',
subtitle: '⚠️ 先进 TC-D10!iOS 单例沉默忽略 + Android 鉴权失败 UI',
builder: () => const TcD13FakeKeyPage(),
),
_DemoItem(
title: 'TC-D14a: Android SurfaceView',
subtitle: '强制 MapView 渲染(androidViewMode=surfaceView)',
builder: () => const TcD14aSurfaceViewPage(),
),
_DemoItem(
title: 'TC-D14b: Android TextureView',
subtitle: '强制 TextureMapView 渲染(androidViewMode=textureView)',
builder: () => const TcD14bTextureViewPage(),
),
],
'1C 地图配置': [
_DemoItem(
title: 'TC-D15: 地图配置',
subtitle:
'mapType / traffic / buildings / labels / customStyleOptions 运行时切换',
builder: () => const TcD15MapConfigPage(),
),
],
'1D UI控件与手势': [
_DemoItem(
title: 'TC-D16: UI控件与手势',
subtitle:
'compass / scale / 手势 / logo / minMaxZoom / limitBounds 运行时切换',
builder: () => const TcD16UiGesturesPage(),
),
_DemoItem(
title: 'TC-D18: 手势冲突 gestureRecognizers',
subtitle: '地图嵌入可滚动 ListView,三种 GestureArena 策略:默认 / Eager / 双指归地图',
builder: () => const TcD18GestureConflictPage(),
),
],
'1G 定位功能': [
_DemoItem(
title: 'TC-D17: 定位图层展示',
subtitle: 'myLocationStyleOptions + updateMyLocation(模拟位置更新)',
builder: () => const TcD17MyLocationPage(),
),
],
'2C/2D 覆盖物': [
_DemoItem(
title: 'TC-D20: Polygon',
subtitle: 'add / change / remove / onTap / visible / dashPattern',
builder: () => const TcD20PolygonPage(),
),
_DemoItem(
title: 'TC-D21: Circle',
subtitle: 'add / change / remove / visible / borderType ⚠️ onTap 不触发',
builder: () => const TcD21CirclePage(),
),
_DemoItem(
title: 'TC-D22: BitmapDescriptor',
subtitle: '定位 icon:fromAsset / fromBytes / disable→re-enable',
builder: () => const TcD22BitmapDescriptorPage(),
),
_DemoItem(
title: 'TC-D24: Widget → Marker',
subtitle: '用户自行将 Widget 离屏渲染为 bytes,再通过 fromBytes 创建 Marker 图标',
builder: () => const TcD24FromWidgetPage(),
),
_DemoItem(
title: 'TC-D23: Polygon 纹理',
subtitle: 'strokeTexture / spacing 调整 / 与 dashPattern 互斥',
builder: () => const TcD23PolygonTexturePage(),
),
_DemoItem(
title: 'TC-D30: Arc 弧线',
subtitle:
'add / change / remove / visible / move(recreate) ⚠️ onTap 不支持',
builder: () => const TcD30ArcPage(),
),
_DemoItem(
title: 'TC-D40: Polyline 折线',
subtitle: 'add / change / remove / onTap / visible / lineCap(recreate)',
builder: () => const TcD40PolylinePage(),
),
_DemoItem(
title: 'TC-D41: Polyline 属性联动',
subtitle: 'lineType/textureLineType/gradient/segmentColors 互斥与压制规则',
builder: () => const TcD41PolylineInteractionPage(),
),
_DemoItem(
title: 'TC-E50: Marker 点标注',
subtitle: 'F00-F17 全字段 toggle / drag / infoWindow / collision',
builder: () => const TcE50MarkerPage(),
),
_DemoItem(
title: 'TC-E51: Marker 碰撞',
subtitle:
'collisionTypes / collisionRelation / zIndex 优先级 / 多 Marker 组合',
builder: () => const TcE51MarkerCollisionPage(),
),
_DemoItem(
title: 'TC-E90: 0.2.1 首屏覆盖物推送修复',
subtitle:
'F01-F11 边界场景:5 类首屏直显 / mapReady 前 pop / burst / 旧 workaround 兼容',
builder: () => const TcE90InitialOverlayPushPage(),
),
],
'地图控制': [
_DemoItem(
title: 'TC-D03: 相机控制',
subtitle: 'CameraUpdate 全部 8 个工厂方法',
builder: () => const MoveCameraPage(),
),
_DemoItem(
title: 'TC-QA01: newLatLngBounds 京沪复现 ⚠️',
subtitle: 'QA 反馈 iOS 卡死:sw=北京/ne=上海(纬度反向非法 bounds)',
builder: () => const TcQa01BoundsFreezePage(),
),
_DemoItem(
title: 'TC-QA02: Polygon 无洞→带洞 update ⚠️',
subtitle: 'QA 反馈 Android SIGSEGV in libtxmapengine nativeUpdatePolygon',
builder: () => const TcQa02PolygonHoleUpdatePage(),
),
_DemoItem(
title: 'TC-QA03: 5000 Marker ANR 复现 ⚠',
subtitle: '批量添加 5000 marker → SurfaceView Fence::waitForever ANR',
builder: () => const TcQa03Marker5kAnrPage(),
),
_DemoItem(
title: 'TC-QA04: Polyline segmentColors 分段不一致 ⚠️',
subtitle: 'QA 反馈 iOS:分段数减少后只显示部分线段(endIndex 语义双端差异)',
builder: () => const TcQa04PolylineSegmentColorsPage(),
),
_DemoItem(
title: 'TC-QA05: Polyline segmentStyles 分段不一致 ⚠️',
subtitle: 'texture/colorSlice 模式:同 segmentColors 问题(endIndex 语义双端差异)',
builder: () => const TcQa05PolylineSegmentStylesPage(),
),
_DemoItem(
title: 'TC-QA06: Polyline points/seg 同步越界 ⚠️',
subtitle: 'points 减少后 segColors/segStyles 的 startIndex 越界(iOS normalize 不裁剪)',
builder: () => const TcQa06PolylinePointsSegSyncPage(),
),
_DemoItem(
title: 'TC-D05: 坐标查询 + 截图',
subtitle: 'getVisibleRegion / getLatLng / takeSnapshot / clearCache',
builder: () => const MapQueryPage(),
),
_DemoItem(
title: 'TC-D05b: 批量坐标转换',
subtitle: 'getScreenCoordinates / getLatLngs 批量转换 + 往返一致性',
builder: () => const TcD05bBatchCoordinatePage(),
),
],
'生命周期': [
_DemoItem(
title: 'TC-D06: 生命周期测试',
subtitle: '快速 dispose 竞态 / 内存泄漏观察',
builder: () => const MapLifecyclePage(),
),
],
'Android 渲染模式(仅 Android 生效)': [
_DemoItem(
title: 'TC-D07: auto 模式',
subtitle: '默认:Android 10+ SurfaceView,10- TextureView',
builder: () => const AndroidViewModePage(
viewMode: AndroidViewMode.auto,
title: 'TC-D07: auto',
),
),
_DemoItem(
title: 'TC-D08: textureView 模式',
subtitle: '强制 TextureView(兼容性最好)',
builder: () => const AndroidViewModePage(
viewMode: AndroidViewMode.textureView,
title: 'TC-D08: textureView',
),
),
_DemoItem(
title: 'TC-D09: surfaceView 模式',
subtitle: '强制 SurfaceView(⚠️ Android 10- 可能闪烁)',
builder: () => const AndroidViewModePage(
viewMode: AndroidViewMode.surfaceView,
title: 'TC-D09: surfaceView',
),
),
],
'开发调试': [
_DemoItem(
title: 'TC-D60: SDK 日志配置',
subtitle: 'enableSdkLog 配置预览 / 调用说明(需冷重启生效)',
builder: () => const TcD60SdkLogPage(),
),
],
};
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Tencent Map Demo')),
body: ListView(
children: _demos.entries.expand((group) {
return [
Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 4),
child: Text(
group.key,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary,
),
),
),
...group.value.map((demo) => ListTile(
title: Text(demo.title),
subtitle:
Text(demo.subtitle, style: const TextStyle(fontSize: 12)),
trailing: const Icon(Icons.chevron_right),
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => demo.builder()),
),
)),
const Divider(height: 1),
];
}).toList(),
),
);
}
}