amap_flutter_sdk 0.1.6
amap_flutter_sdk: ^0.1.6 copied to clipboard
Unified AMap Flutter SDK — Map, Location and Search for Android & iOS. Unofficial community plugin; not affiliated with Amap.
example/lib/main.dart
import 'package:amap_flutter_sdk/amap_flutter_sdk.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
/// 请替换为你在高德开放平台申请的 Key
const _androidKey = 'YOUR_ANDROID_KEY';
const _iosKey = 'YOUR_IOS_KEY';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AMap Flutter SDK Demo',
theme: ThemeData(colorSchemeSeed: Colors.blue, useMaterial3: true),
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _ready = false;
@override
void initState() {
super.initState();
_initSdk();
}
Future<void> _initSdk() async {
await AMapSdk.init(
androidKey: _androidKey,
iosKey: _iosKey,
privacy: const AMapPrivacy(),
);
if (mounted) setState(() => _ready = true);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('amap_flutter_sdk Demo')),
body: !_ready
? const Center(child: CircularProgressIndicator())
: ListView(
children: [
ListTile(
title: const Text('地图 Map'),
subtitle: const Text('AMapView / Marker / Camera'),
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const MapDemoPage()),
),
),
ListTile(
title: const Text('定位 Location'),
subtitle: const Text('单次/连续定位'),
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const LocationDemoPage()),
),
),
ListTile(
title: const Text('搜索 Search'),
subtitle: const Text('POI / 地理编码 / 行政区'),
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const SearchDemoPage()),
),
),
],
),
);
}
}
class MapDemoPage extends StatefulWidget {
const MapDemoPage({super.key});
@override
State<MapDemoPage> createState() => _MapDemoPageState();
}
class _MapDemoPageState extends State<MapDemoPage> {
AMapController? _controller;
final Map<String, Marker> _markers = {};
@override
Widget build(BuildContext context) {
AMapSdk.ensureMapReady(
context,
androidKey: _androidKey,
iosKey: _iosKey,
);
return Scaffold(
appBar: AppBar(title: const Text('地图')),
body: AMapView(
initialCameraPosition: const CameraPosition(
target: LatLng(39.909187, 116.397451),
zoom: 12,
),
markers: Set<Marker>.of(_markers.values),
onMapCreated: (c) {
_controller = c;
final m = Marker(
position: const LatLng(39.909187, 116.397451),
infoWindow: const InfoWindow(title: '天安门'),
);
setState(() => _markers[m.id] = m);
},
onTap: (latLng) {
_controller?.moveCamera(
CameraUpdate.newLatLng(latLng),
animated: true,
);
},
),
);
}
}
class LocationDemoPage extends StatefulWidget {
const LocationDemoPage({super.key});
@override
State<LocationDemoPage> createState() => _LocationDemoPageState();
}
class _LocationDemoPageState extends State<LocationDemoPage> {
final _client = AMapLocationClient();
String _text = '未开始';
@override
void initState() {
super.initState();
_client.onLocationChanged().listen((r) {
setState(() {
if (!r.isSuccess) {
_text = '失败: ${r.errorCode} ${r.errorInfo}';
} else {
_text =
'${r.latitude}, ${r.longitude}\n${r.address ?? r.description ?? ''}';
}
});
});
}
Future<void> _start() async {
final status = await Permission.locationWhenInUse.request();
if (!status.isGranted) {
setState(() => _text = '无定位权限');
return;
}
await _client.setLocationOption(AMapLocationOption(
onceLocation: true,
needAddress: true,
locationMode: AMapLocationMode.highAccuracy,
));
await _client.startLocation();
}
@override
void dispose() {
_client.destroy();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('定位')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ElevatedButton(onPressed: _start, child: const Text('开始定位')),
const SizedBox(height: 16),
Text(_text),
],
),
),
);
}
}
class SearchDemoPage extends StatefulWidget {
const SearchDemoPage({super.key});
@override
State<SearchDemoPage> createState() => _SearchDemoPageState();
}
class _SearchDemoPageState extends State<SearchDemoPage> {
final _keyword = TextEditingController(text: '北京大学');
String _result = '';
Future<void> _searchPoi() async {
try {
final r = await AMapSearchClient.searchPoi(
keyword: _keyword.text,
city: '北京',
);
setState(() {
_result = r.pois
.take(10)
.map((e) => '${e.name} (${e.location?.latitude},${e.location?.longitude})')
.join('\n');
});
} catch (e) {
setState(() => _result = 'POI 失败: $e');
}
}
Future<void> _geocode() async {
try {
final list = await AMapSearchClient.geocode(
address: _keyword.text,
city: '北京',
);
setState(() {
_result = list
.map((e) =>
'${e.formattedAddress} -> ${e.location?.latitude},${e.location?.longitude}')
.join('\n');
});
} catch (e) {
setState(() => _result = '地理编码失败: $e');
}
}
Future<void> _regeocode() async {
try {
final r = await AMapSearchClient.regeocode(
location: const LatLng(39.909187, 116.397451),
);
setState(() => _result = r.formattedAddress);
} catch (e) {
setState(() => _result = '逆地理失败: $e');
}
}
Future<void> _district() async {
try {
final list = await AMapSearchClient.searchDistrict(keyword: '北京市');
setState(() {
_result = list
.map((e) =>
'${e.name} ${e.adCode} children=${e.districts.length}')
.join('\n');
});
} catch (e) {
setState(() => _result = '行政区失败: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('搜索')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
TextField(controller: _keyword, decoration: const InputDecoration(labelText: '关键字/地址')),
Wrap(
spacing: 8,
children: [
ElevatedButton(onPressed: _searchPoi, child: const Text('POI')),
ElevatedButton(onPressed: _geocode, child: const Text('地理编码')),
ElevatedButton(onPressed: _regeocode, child: const Text('逆地理')),
ElevatedButton(onPressed: _district, child: const Text('行政区')),
],
),
const SizedBox(height: 12),
Expanded(child: SingleChildScrollView(child: Text(_result))),
],
),
),
);
}
}