今天这篇博客说的是地图和定位的问题,不一样的是,这是在flutter中处理地图,定位,反地理编码。
先看下做出来的效果如何:

目前用到的都是模拟数据,真实场景大家自己接入数据即可。
这里的功能分为几部分:
1.百度地图;
2.定位功能;(百度地图提供了定位功能,需要单独引入,但是这里选择使用其他的基于LBS的定位)
3.反地理编码;
4.抽屉功能;(就是这个可以拖拽的列表,可展开,可折叠)
5.滑动按钮;
6.插旗和更新位置信息;
7.总结和页面完整代码。
然后我们来一步步说明怎么来使用这些功能:
1.百度地图
百度地图flutter插件接入地址:http://lbsyun.baidu.com/index.php?title=flutter/loc
至于接入的部分,大家参照文档来接入,不再赘述。
引入地图库:
flutter_baidu_mapapi_map: ^2.0.0
地图在接入后需要初始化:
// 百度地图sdk初始化鉴权
if (Platform.isIOS) {
BMFMapSDK.setApiKeyAndCoordType(
'xxxxxxxxxxxxxxxxxxxx', BMF_COORD_TYPE.COMMON);
} else if (Platform.isAndroid) {
// Android 目前不支持接口设置Apikey,
// 请在主工程的Manifest文件里设置,详细配置方法请参考官网(https://lbsyun.baidu.com/)demo
BMFMapSDK.setCoordType(BMF_COORD_TYPE.COMMON);
}
这样就完成了地图的接入准备工作。
接着我们来创建地图:
@override
Container generateMap() {
return Container(
height: screenSize.height,
width: screenSize.width,
child: BMFMapWidget(
onBMFMapCreated: (controller) {
onBMFMapCreated(controller);
},
mapOptions: initMapOptions(latitude: dposition?.latitude ?? (widget.latitude ?? 39.928617), longitude: dposition?.longitude ?? (widget.longitude ?? 116.40329))
),
);
}
/// 设置地图参数
BMFMapOptions initMapOptions({double latitude, double longitude}) {
BMFCoordinate coordinate = BMFCoordinate(latitude ??widget.latitude, longitude ?? widget.longitude);
BMFMapOptions mapOptions = BMFMapOptions(
center: coordinate,
zoomLevel: 12,
mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 0));
return mapOptions;
}
这里,iOS要注意两个点:
1.要设置Bundle display name,否则iOS地图启动会失败;
2.新项目要添加SWIFT_VERSION,否则会报大量的swift错误,项目无法运行;

2.定位功能
百度地图提供了定位的功能,和百度地图也是配套使用的,
引入定位插件:
flutter_bmflocation: ^1.0.2
这里官网有个误解:

看这张图,按照图上的指引去配置,根本跑不起来,这也是为什么博主选择通过其他方式来定位的原因,后面提了工单,说是不需要做任何的配置,pod install之后会自动完成所有的配置,大家可以自己尝试下,相信官方不至于乱说,这里切记一定不要手动配置。
那这里说说博主是怎么不通过百度定位来做定位功能的:
首先引入定位的库:
geolocator: 6.2.1
这里的版本建议大家写死,因为在之前的版本定位和反地理编码是在同一个库里面的,后面拆开了,稍后会说反地理编码的库。
///定位功能,会获取接触的经纬度信息
Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best);
3.反地理编码
定位里面说了,反地理编码是在定位的库里面拆分出来的,这里引入的库名为:
geocoding: 1.0.1
反地理编码需要在真机上才能执行,注意下,代码如下:
Future<String> _getAddressFromLatLng() async {
try {
List<Placemark> p = await placemarkFromCoordinates(
dposition?.latitude ?? 39.928617, dposition?.longitude ?? 116.40329);
Placemark place = p[0];
print("${place?.locality ?? ''}${place?.subLocality ?? ''}${place?.street ?? ''}");
String locationStr = "${place?.locality ?? ''}${place?.subLocality ?? ''}${place?.street ?? ''}";
_marker.updateSubTitle(locationStr);
return locationStr;
} catch (e) {
print(e);
}
}
这个方法会返回地理位置的名字,这个方法很简单。
4.抽屉功能
这个抽屉的功能稍微有点复杂,推荐使用一个库:
drag_container: 1.0.2
使用介绍:
///构建底部对齐的抽屉效果视图
Widget buildDragWidget(){
///层叠布局中的底部对齐
return Align(
alignment: Alignment.bottomCenter,
child: DragContainer(
///抽屉关闭时的高度 默认0.4
initChildRate: 0.2,
///抽屉打开时的高度 默认0.4
maxChildRate: 0.9,
///是否显示默认的标题
isShowHeader: true,
///背景颜色
backGroundColor: Colors.transparent,
///背景圆角大小
cornerRadius: 12,
///自动上滑动或者是下滑的分界值
maxOffsetDistance:1.5,
///抽屉控制器
controller: dragController,
///滑动控制器
scrollController: scrollController,
///自动滑动的时间
duration: Duration(milliseconds: 800),
///抽屉的子Widget
dragWidget: buildListView(),
///抽屉标题点击事件回调
dragCallBack: (isOpen){
_show = isOpen;
setState(() {
});
},
///列表到顶向下滑动可关闭
useAtEdge: true,
),
);
}
buildListView就写自己的列表Ui就可以了,里面属性很多,根据自己的需要来设置。
5.滑动按钮
说起来,flutter的轮子还是比较全的哈,这里还是给大家安利一个组件:
slider_button: ^0.6.0
SliderButton(
boxShadow: BoxShadow(
color: Colors.blue,
blurRadius: 2,
),
width: (MediaQuery.of(context).size.width - 56 - 16) / 2,
height: 36,
buttonSize: 20,
radius: 18,
alignLabel: Alignment(0.1, 0),
buttonColor: Colors.white,
backgroundColor: Colors.blue,
shimmer: false,
dismissible: false,
label: Text(
"滑动确认送达",
style: TextStyle(fontSize: 12, color: Colors.white),
),
icon: Center(
child: Icon(
Icons.arrow_forward_ios,
color: Colors.blue,
size: 12.0,
semanticLabel: 'Text to announce in accessibility modes',
)
),
action: () {
},
),
按钮中的各个元素需要根据实际情况来设置,如果设置不好的话按钮的样子就很丑啦。
6.插旗和更新位置信息
地图上标记位置,并实时更新位置信息是需要我们自己来写交互的,看如下方法:
1.添加大头针:
/// 添加大头针
Future<void> addMarker() async {
BMFCoordinate coordinate = BMFCoordinate(widget.latitude ?? 39.928617, widget.longitude ?? 116.40329);
_getAddressFromLatLng().then((value) {
BMFMarker marker = BMFMarker(
position: coordinate,
title: '配送员配送中',
subtitle: value ?? '',
identifier: 'flutter_marker',
icon: 'resoures/route_detail_start.png');
myMapController?.addMarker(marker);
_marker = marker;
});
if (_timer == null) {
_timer = Timer.periodic(Duration(milliseconds: 10000), (timer) async {
reloadLocation();
});
}
}
_getAddressFromLatLng是反地理编码,上面已经给出了代码。
2.更新大头针位置和地图的中心点
Future<void> reloadLocation() async {
dposition = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best);
_getAddressFromLatLng();
if (dposition != null) {
print(dposition);
BMFCoordinate coordinate = BMFCoordinate(dposition?.latitude ?? 39.928617, dposition?.longitude ?? 116.40329);
///更新插旗的位置
_marker.updatePosition(coordinate);
///设置地图中心点
myMapController?.setCenterCoordinate(coordinate, true);
}
}
7.总结和页面完整代码
总的来说,flutter目前的轮子还是比较多的,很多复杂的功能都能够实现,要么官方提供了轮子,要么就是其他大佬写好的。
这个页面接本都是采用了其他开发者提供的组件来完成,这样看下来,功能的复杂度都降低了很多,这里只是给大家提供个思路,希望给大家能带来帮助。
这里提供下完整的代码:
引入库:
slider_button: ^0.6.0
flutter_baidu_mapapi_map: ^2.0.0
permission_handler: ^5.0.1+1
geolocator: 6.2.1
geocoding: 1.0.1
drag_container: 1.0.2
引入百度资源:
assets:
- resoures/
- files/
- resoures/bmflocaltileimage/16/
- resoures/bmflocaltileimage/17/
这个大家参考百度的demo,把资源拿过来
页面类配送页面:
import 'dart:async';
import 'dart:io';
import 'package:drag_container/drag/drag_container.dart';
import 'package:flutter/material.dart';
import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart';
import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart';
import 'package:flutter_map/sending_list_widget.dart';
import 'package:geolocator/geo
本文介绍了在Flutter中如何接入百度地图,实现定位、反地理编码和配送员界面功能。通过引入地图库、设置初始化,创建地图,并利用特定库实现定位和反地理编码。同时,展示了抽屉功能、滑动按钮、插旗更新位置等组件的实现,提供了完整页面代码供参考。
订阅专栏 解锁全文
1409





