一、引用flutter插件:
flutter_baidu_mapapi_map: ^3.0.0+2
flutter_baidu_mapapi_search: ^3.0.0
flutter_bmflocation: ^3.2.0
声明变量:
final LocationFlutterPlugin _myLocPlugin = LocationFlutterPlugin();
BMFMapController? myMapController;
BaiduLocation? resultLocation;
BMFMapOptions? mapOptions;
List
二、配置iOS ,安卓使用权限
具体查看官网: flutter | 百度地图API SDK
三、初始化百度SDK
class baiduMapMethod {
baiduInit() {
LocationFlutterPlugin myLocPlugin = LocationFlutterPlugin();
/// 设置用户是否同意SDK隐私协议
/// since 3.1.0 开发者必须设置
BMFMapSDK.setAgreePrivacy(true);
myLocPlugin.setAgreePrivacy(true);
// 百度地图sdk初始化鉴权
if (Platform.isIOS) {
myLocPlugin.authAK('z1B4qRV0Q1mI7wPeuwiXWWr1SBNXvoQ1');
BMFMapSDK.setApiKeyAndCoordType(
'百度控制台申请的appkey', BMF_COORD_TYPE.BD09LL);
} else if (Platform.isAndroid) {
// Android 目前不支持接口设置Apikey,
// 请在主工程的Manifest文件里设置,详细配置方法请参考官网(https://lbsyun.baidu.com/)demo
BMFMapSDK.setCoordType(BMF_COORD_TYPE.BD09LL);
}
}
}
var baiduMapSDK = baiduMapMethod();
四、设置定位参数(安卓可以, 但iOS设置之后百度无法回调定位信息, 暂时没法解决)
// 设置定位参数
setLocation() {
BaiduLocationIOSOption iosOptions = BaiduLocationIOSOption(
// 坐标系
coordType: BMFLocationCoordType.bd09ll,
// 位置获取超时时间
locationTimeout: 10,
// 获取地址信息超时时间
reGeocodeTimeout: 10,
// 应用位置类型 默认为automotiveNavigation
activityType: BMFActivityType.automotiveNavigation,
// 设置预期精度参数 默认为best
desiredAccuracy: BMFDesiredAccuracy.best,
// 是否需要最新版本rgc数据
isNeedNewVersionRgc: true,
// 指定定位是否会被系统自动暂停
pausesLocationUpdatesAutomatically: false,
// 指定是否允许后台定位,
// 允许的话是可以进行后台定位的,但需要项目
//配置允许后台定位,否则会报错,具体参考开发文档
allowsBackgroundLocationUpdates: true,
// 设定定位的最小更新距离
distanceFilter: 10,
);
Map iosMap = iosOptions.getMap();
BaiduLocationAndroidOption androidOptions = BaiduLocationAndroidOption(
// 定位模式,可选的模式有高精度、仅设备、仅网络。默
// 认为高精度模式
locationMode: BMFLocationMode.hightAccuracy,
// 是否需要返回地址信息
isNeedAddress: true,
// 是否需要返回海拔高度信息
isNeedAltitude: false,
// 是否需要返回周边poi信息
isNeedLocationPoiList: true,
// 是否需要返回新版本rgc信息
isNeedNewVersionRgc: true,
// 是否需要返回位置描述信息
isNeedLocationDescribe: true,
// 是否使用gps
openGps: true,
// 可选,设置场景定位参数,包括签到场景、运动场景、出行场景
locationPurpose: BMFLocationPurpose.sport,
// 坐标系
coordType: BMFLocationCoordType.bd09ll,
// 设置发起定位请求的间隔,int类型,单位ms
// 如果设置为0,则代表单次定位,即仅定位一次,默认为0
scanspan: 0);
Map androidMap = androidOptions.getMap();
_myLocPlugin.prepareLoc(androidMap, {}); // ios置空
}
五、接受定位回调
// 接受定位回调
acceptPosition() {
if (Platform.isIOS) {
//接受定位回调
_myLocPlugin.singleLocationCallback(callback: (BaiduLocation result) {
hideLoading();
resultLocation = result;
if (result.errorInfo != null) {
showToast('请开启您的定位');
return;
}
sendBaiduPOI(result, result.address);
});
} else if (Platform.isAndroid) {
//接受定位回调
_myLocPlugin.stopLocation();
_myLocPlugin.seriesLocationCallback(callback: (BaiduLocation result) {
hideLoading();
resultLocation = result;
if (result.errorInfo != null) {
showToast('请开启您的定位');
return;
}
sendBaiduPOI(result, result.address);
});
}
}
六、开启定位
// 开启定位
startLocation() async {
showLoading();
await _myLocPlugin
.singleLocation({'isReGeocode': true, 'isNetworkState': true});
}
七、位置检索(poi)
sendBaiduPOI(BaiduLocation location, String? searchString) async {
// 构造检索参数
BMFPoiNearbySearchOption poiNearbySearchOption = BMFPoiNearbySearchOption(
keywords:
location: BMFCoordinate(
location.latitude ?? 23.0000000, location.longitude ?? 113.287361),
radius: 1000,
isRadiusLimit: true);
// 检索实例
BMFPoiNearbySearch nearbySearch = BMFPoiNearbySearch();
// 检索回调
nearbySearch.onGetPoiNearbySearchResult(
callback: (BMFPoiSearchResult result, BMFSearchErrorCode errorCode) {
if (result.poiInfoList != null) {
mapModelList.clear();
int i = 0;
for (var element in result.poiInfoList!) {
mapModelList.add(mapListModel(
title: element.name,
address: element.address,
isSelect: i == 0 ? true : false,
latitude: element.pt?.latitude,
longitude: element.pt?.longitude));
i++;
}
setState(() {});
} else {
showToast('附近暂无搜索位置');
}
if (mapModelList.isNotEmpty) {
dataFullt(BMFCoordinate(
mapModelList[0].latitude!, mapModelList[0].longitude!));
}
print(
'poi周边检索回调 errorCode = ${errorCode} \n result = ${result.toMap()}');
// 解析reslut,具体参考demo
});
// 发起检索
bool flag = await nearbySearch.poiNearbySearch(poiNearbySearchOption);
print(flag);
}
八、数据渲染
// 数据渲染
dataFullt(BMFCoordinate Coordinate) {
//result为定位结果
mapOptions = BMFMapOptions(
center: Coordinate,
zoomLevel: 19,
compassEnabled: true,
showMapPoi: true,
showMapScaleBar: false,
mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 0));
setState(() {
showMap = true;
});
mapLocation(mapModelList[0].latitude, mapModelList[0].longitude);
}
九、地图显示
// 地图显示
Container mapListView() {
return Container(
height: ScreenUtils.screenHeight - ScreenUtils.screenHeight / 2 - 121.w,
child: ListView.builder(
itemBuilder: (context, index) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
selectIndex = index;
for (var i = 0; i < mapModelList.length; i++) {
mapModelList[i].isSelect = false;
if (i == index) {
mapModelList[i].isSelect = true;
}
}
mapLocation(
mapModelList[index].latitude, mapModelList[index].longitude);
setState(() {});
},
child: Padding(
padding: EdgeInsets.only(
top: 8.0.h, bottom: 10.0.h, left: 15.0.w, right: 15.0.w),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: ScreenUtils.screenWidth - 80.w,
child: Text(mapModelList[index].title ?? ''),
),
Container(
width: ScreenUtils.screenWidth - 80.w,
child: Text(
mapModelList[index].address ?? '',
style: TextStyle(
overflow: TextOverflow.ellipsis,
color: const Color(0xFF666666),
fontSize: 12.sp),
),
),
],
),
if (mapModelList[index].isSelect)
Image(
width: 15.w,
height: 15.h,
image: const AssetImage(
'assets/images/icon_food_gou_b.png'))
],
),
Padding(
padding: EdgeInsets.only(top: 10.w),
child: SizedBox(
width: ScreenUtils.screenWidth - 35,
height: 0.5.w,
child: Container(
decoration:
const BoxDecoration(color: Color(0xFFF0F0F0)),
),
),
)
],
),
),
);
},
itemCount: mapModelList.length,
),
);
}
/// 创建完成回调
void onBMFMapCreated(BMFMapController controller) {
myMapController = controller;
/// 地图加载回调
myMapController?.setMapDidLoadCallback(callback: () {
print('mapDidLoad-地图加载完成');
});
}
十、移动点定位(设置大头针)
// 移动点定位
void mapLocation(lat, lng) {
myMapController?.showUserLocation(true);
BMFCoordinate coordinate = BMFCoordinate(lat, lng); // 经纬度信息
BMFLocation location = BMFLocation(
// 定位信息
coordinate: coordinate, // 经纬度
altitude: 0, // 海拔
horizontalAccuracy: 5, // 水平精确度
verticalAccuracy: -1.0, // 垂直精确度
speed: -1.0, // 速度
course: -1.0); // 航向
BMFUserLocation userLocation = BMFUserLocation(
// 当前位置对象
location: location,
);
myMapController?.updateLocationData(userLocation); // 动态更新我的位置数据
BMFUserLocationDisplayParam displayParam = BMFUserLocationDisplayParam(
locationViewOffsetX: 0,
locationViewOffsetY: 0,
accuracyCircleFillColor: Colors.green,
accuracyCircleStrokeColor: Colors.blue,
isAccuracyCircleShow: true,
locationViewImage: 'assets/images/map_datouzhen.png',
locationViewHierarchy:
BMFLocationViewHierarchy.LOCATION_VIEW_HIERARCHY_TOP);
myMapController?.updateLocationViewWithParam(displayParam); // 动态定制我的位置样式
}
十一、 注意事项
1. 百度渲染地图widget使用: 安卓: BMFTextureMapWidget ,iOS : BMFMapWidget (特坑, 文档没有说明,安卓会显示全屏, 顶掉导航栏)
2. 注意安卓配置权限部分, MyApplication.Java文件放在kotlin文件夹里面
3. 安卓部分一定要设置定位参数, iOS不需要, 目前不知道什么原因导致iOS设置定位参数之后无法启动
4. dispose要加入_myLocPlugin.stopLocation(); // 结束定位