Flutter地图展示插件free_map的使用
Flutter地图展示插件free_map的使用
free_map
是一个由OpenStreetMap支持的Flutter包,它提供了免费的地图服务、地址自动补全文本框、绘制多段线、地理编码和反向地理编码等功能。
功能特性
- 地址搜索:提供带有自动补全功能的文本框进行地址搜索。
- 地图特性:添加标记、绘制多段线、点击选择位置以及通过控制器精细控制地图。
- 地理编码:从地址获取地理坐标。
- 反向地理编码:从地理坐标检索地址。
- 基于OpenStreetMap:一个免费的开源替代方案,与Google Maps类似。
- 高度可定制:调整小部件外观以匹配您的应用程序设计。
入门指南
Android配置
在AndroidManifest.xml
文件中添加互联网权限:
<uses-permission android:name="android.permission.INTERNET" />
使用方法
以下是free_map
的主要组件及其用法示例:
自动补全文本框
用于地址搜索的自动补全文本框,用户可以输入地址并从建议列表中选择。
FmSearchField(
selectedValue: _address,
searchParams: const FmSearchParams(),
onSelected: (data) => _address = data,
textFieldBuilder: (focus, controller, onChanged) {
return TextFormField(
focusNode: focus,
onChanged: onChanged,
controller: controller,
decoration: InputDecoration(
filled: true,
hintText: 'Search',
fillColor: Colors.grey[300],
suffixIcon: controller.text.trim().isEmpty || !focus.hasFocus
? null
: IconButton(
padding: EdgeInsets.zero,
icon: const Icon(Icons.close),
onPressed: controller.clear,
visualDensity: VisualDensity.compact,
),
),
);
},
)
地图小部件
显示地图的小部件,可以添加标记、多段线等元素,并监听点击事件。
FmMap(
mapController: _mapController,
mapOptions: MapOptions(
minZoom: 15,
maxZoom: 18,
initialZoom: 15,
initialCenter: _src,
onTap: (pos, point) => _getAddress(point),
),
markers: [
Marker(
point: _src,
child: const Icon(
size: 40.0,
color: Colors.red,
Icons.location_on_rounded,
),
),
Marker(
point: _dest,
child: const Icon(
size: 40.0,
color: Colors.blue,
Icons.location_on_rounded,
),
),
],
polylineOptions: const FmPolylineOptions(
strokeWidth: 3,
color: Colors.blue,
),
),
地理编码
根据提供的地址获取其对应的地理坐标。
final data = await FmService().getGeocode(address: address);
反向地理编码
根据提供的地理坐标获取其对应的地址信息。
final data = await FmService().getAddress(
lat: pos.latitude,
lng: pos.longitude,
);
示例代码
下面是一个完整的演示示例,展示了如何在一个简单的Flutter应用中集成free_map
插件的功能。
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:free_map/free_map.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
FmData? _address;
late final MapController _mapController;
final _src = const LatLng(37.4165849896396, -122.08051867783071);
final _dest = const LatLng(37.420921119071586, -122.08535335958004);
@override
void initState() {
super.initState();
_mapController = MapController();
}
@override
void dispose() {
_mapController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Builder(builder: (context) {
return GestureDetector(
onTap: FocusScope.of(context).unfocus,
child: Scaffold(
appBar: AppBar(title: const Text('Free Map Demo')),
body: SafeArea(
bottom: false,
child: Stack(children: [_map, _searchField]),
),
),
);
}),
);
}
/// Free map widget
Widget get _map {
return FmMap(
mapController: _mapController,
mapOptions: MapOptions(
minZoom: 15,
maxZoom: 18,
initialZoom: 15,
initialCenter: _src,
onTap: (pos, point) => _getAddress(point),
),
markers: [
Marker(
point: _src,
child: const Icon(
size: 40.0,
color: Colors.red,
Icons.location_on_rounded,
),
),
Marker(
point: _dest,
child: const Icon(
size: 40.0,
color: Colors.blue,
Icons.location_on_rounded,
),
),
],
polylineOptions: const FmPolylineOptions(
strokeWidth: 3,
color: Colors.blue,
),
);
}
/// Auto-complete places search field
Widget get _searchField {
return Padding(
padding: const EdgeInsets.all(20.0),
child: FmSearchField(
selectedValue: _address,
searchParams: const FmSearchParams(),
onSelected: (data) => _address = data,
textFieldBuilder: (focus, controller, onChanged) {
return TextFormField(
focusNode: focus,
onChanged: onChanged,
controller: controller,
decoration: InputDecoration(
filled: true,
hintText: 'Search',
fillColor: Colors.grey[300],
suffixIcon: controller.text.trim().isEmpty || !focus.hasFocus
? null
: IconButton(
padding: EdgeInsets.zero,
icon: const Icon(Icons.close),
onPressed: controller.clear,
visualDensity: VisualDensity.compact,
),
),
);
},
),
);
}
/// REVERSE GEOCODING: Get address from geocode
Future<void> _getAddress(LatLng pos) async {
final data = await FmService().getAddress(
lat: pos.latitude,
lng: pos.longitude,
);
if (kDebugMode) print(data?.address);
if (data != null) _getGeocode(data.address);
}
/// GEOCODING: Get geocode from an address
Future<void> _getGeocode(String address) async {
final data = await FmService().getGeocode(address: address);
if (kDebugMode) print('${data?.lat},${data?.lng}');
}
}
这个示例创建了一个包含地图和搜索框的应用程序。用户可以在搜索框中输入地址,地图上会显示两个预定义的位置(起点和终点),并且可以通过点击地图上的任意位置来获取该位置的地址信息。
如果您发现任何问题或希望看到新功能,请访问 Issues 部分提交反馈。
更多关于Flutter地图展示插件free_map的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter地图展示插件free_map的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter应用中使用free_map
插件来展示地图的代码示例。请注意,free_map
可能不是官方或广泛使用的插件名称,这里我假设它是一个类似功能的地图展示插件。实际使用中,你可能需要查找并安装具体的地图展示插件,例如flutter_map
或google_maps_flutter
。不过,为了贴合你的要求,我将提供一个假设性的free_map
插件使用示例。
首先,确保你的Flutter项目已经创建,并在pubspec.yaml
文件中添加free_map
依赖(注意:这里的free_map
是假设的,实际使用时请替换为真实的插件名称):
dependencies:
flutter:
sdk: flutter
free_map: ^latest_version # 替换为实际插件的最新版本号
然后运行flutter pub get
来安装依赖。
接下来,在你的Flutter应用中使用free_map
插件来展示地图。以下是一个简单的示例代码:
import 'package:flutter/material.dart';
import 'package:free_map/free_map.dart'; // 假设的插件导入路径
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Map Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MapScreen(),
);
}
}
class MapScreen extends StatefulWidget {
@override
_MapScreenState createState() => _MapScreenState();
}
class _MapScreenState extends State<MapScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Map Demo'),
),
body: Center(
child: FreeMapWidget( // 假设的地图组件
initialCameraPosition: CameraPosition(
target: LatLng(37.7749, -122.4194), // 旧金山坐标
zoom: 14.0,
),
markers: [
Marker(
markerId: MarkerId('san_francisco'),
position: LatLng(37.7749, -122.4194),
infoWindow: InfoWindow(title: 'San Francisco', snippet: 'USA'),
),
],
),
),
);
}
}
// 假设的CameraPosition和LatLng类定义(实际插件中可能已有定义)
class CameraPosition {
final LatLng target;
final double zoom;
CameraPosition({required this.target, required this.zoom});
}
class LatLng {
final double latitude;
final double longitude;
LatLng(this.latitude, this.longitude);
}
class Marker {
final MarkerId markerId;
final LatLng position;
final InfoWindow infoWindow;
Marker({required this.markerId, required this.position, required this.infoWindow});
}
class MarkerId {
final String value;
MarkerId(this.value);
}
class InfoWindow {
final String title;
final String snippet;
InfoWindow({required this.title, required this.snippet});
}
// 注意:上面的CameraPosition, LatLng, Marker, MarkerId, InfoWindow类是为了演示目的而假设的。
// 在实际使用的插件中,这些类通常已经由插件提供,无需自行定义。
请注意,上面的代码示例中FreeMapWidget
, CameraPosition
, LatLng
, Marker
, MarkerId
, 和 InfoWindow
类是基于假设的,因为free_map
插件并非一个真实存在的广泛使用的插件名称。在实际使用中,你需要参考所使用插件的文档来了解如何正确导入和使用这些类和组件。
对于真实的地图展示插件,例如flutter_map
或google_maps_flutter
,它们的用法和组件会有所不同,因此请务必查阅官方文档或相关教程来获取正确的使用方法和代码示例。