未經本人同意,禁止轉載!
前幾天開發flutter百度地圖,總算是把第一步走通了,這幾天把定位功能開發了一下,記錄一下,所謂取之于CSDN用之于CSDN,
下面描述的工程是配置Android的,ios并沒有配置,
開發環境:sdk: “>=2.12.0 < 3.0.0”
Android Studio版本3.4.0
文章目錄
- 前言
- 一、引入官網的集成百度地圖定位Flutter插件
- 二、匯入dart類,使用對外介面
- 三、創建主界面代碼
- 四、啟動定位
- 五、停止定位
- 六、動態申請定位權限,并進行監聽
- 七、移動點定位
- 八、全部代碼,可直接復制使用,已添加空安全檢測
- 九、實作效果
- 十、總結
前言
前面地圖的步驟,直接按照百度地圖保姆級教程(1) 來進行地圖的引入即可,包括AK秘鑰的引入,地圖的顯示等,下面的教程都是基于上面的所有步驟完成,地圖正確顯示之后,才能夠進行,在(1)的代碼基礎上進行添加,部分步驟可以直接按照官網提供的來
flutter sdk2.9.0之后都是支持空安全檢測的,
一、引入官網的集成百度地圖定位Flutter插件
定位插件引入就引入官網提供的最新版本的,不然可能會出現空安全檢測的警告:
flutter_bmflocation: ^2.0.0-nullsafety.0
二、匯入dart類,使用對外介面
import ‘package:flutter_bmflocation/bdmap_location_flutter_plugin.dart’;
import ‘package:flutter_bmflocation/flutter_baidu_location.dart’;
import ‘package:flutter_bmflocation/flutter_baidu_location_android_option.dart’;
import ‘package:flutter_bmflocation/flutter_baidu_location_ios_option.dart’;
三、創建主界面代碼
使用stack組件進行層疊式布局,將開始定位和停止定位按鈕疊加在地圖上面,用于控制是否進行定位操作,沒怎么調整樣式,只是先實作的功能,
Scaffold(
body:Container(
width: screenSize.width,
height: screenSize.height,
child: Stack(
alignment:Alignment.center , //指定未定位或部分定位widget的對齊方式
children: <Widget>[
Container(
child:BMFMapWidget(
onBMFMapCreated: (controller) { // 創建mapView回呼
onBMFMapCreated(controller);
},
mapOptions: initMapOptions(), // 設定map地圖引數
),
),
Positioned( // 這部分是用來切換衛星地圖和普通地圖
top: 0.0,
child: mapTypeSelect(),
),
Positioned( // 這部分用來顯示經緯度資訊和時間資訊,都可以自己隨意定義
top: 50,
child:Row(
children: widgets,
),
),
Positioned(
top: 70,
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new RaisedButton(
onPressed: _startLocation, // 控制開始定位
child: new Text('開始定位'),
color: Colors.blue,
textColor: Colors.white,
),
new Container(width: 20.0),
new RaisedButton(
onPressed: _stopLocation, // 控制停止定位
child: new Text('停止定位'),
color: Colors.blue,
textColor: Colors.white,
)
],
),
)
],
),
),
);
// 選擇組件
Widget mapTypeSelect() {
return Container(
height: 50.00,
decoration: BoxDecoration(
color: Colors.blue,
),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
///包裹子布局
mainAxisSize: MainAxisSize.max,
children: [
Radio(
///此單選框系結的值 必選引數
value: 'false',
///當前組中這選定的值 必選引數
groupValue: _groupValue,
///點擊狀態改變時的回呼 必選引數
onChanged: (v) {
myMapController?.updateMapOptions(BMFMapOptions(mapType: BMFMapType.Standard));
setState(() {
this._groupValue = v;
});
},
),
Text("普通地圖",style: TextStyle(color: Colors.white))
],
),
Row(
///包裹子布局
mainAxisSize: MainAxisSize.max,
children: [
Radio(
///此單選框系結的值 必選引數
value: 'true',
///當前組中這選定的值 必選引數
groupValue: _groupValue,
///點擊狀態改變時的回呼 必選引數
onChanged: (v) {
myMapController?.updateMapOptions(BMFMapOptions(mapType: BMFMapType.Satellite));
setState(() {
this._groupValue = v;
});
},
),
Text("衛星地圖",style: TextStyle(color: Colors.white))
],
),
]
),
);
}
四、啟動定位
準備定位,配置Android端的定位引數
/// 設定android端和ios端定位引數
void _setLocOption() {
/// android 端設定定位引數
BaiduLocationAndroidOption androidOption = new BaiduLocationAndroidOption();
androidOption.setCoorType("bd09ll"); // 設定回傳的位置坐標系型別
androidOption.setIsNeedAltitude(true); // 設定是否需要回傳海拔高度資訊
androidOption.setIsNeedAddres(true); // 設定是否需要回傳地址資訊
androidOption.setIsNeedLocationPoiList(true); // 設定是否需要回傳周邊poi資訊
androidOption.setIsNeedNewVersionRgc(true); // 設定是否需要回傳最新版本rgc資訊
androidOption.setIsNeedLocationDescribe(true); // 設定是否需要回傳位置描述
androidOption.setOpenGps(true); // 設定是否需要使用gps
androidOption.setLocationMode(LocationMode.Hight_Accuracy); // 設定定位模式
androidOption.setScanspan(1000); // 設定發起定位請求時間間隔
Map androidMap = androidOption.getMap();
/// ios 端設定定位引數
BaiduLocationIOSOption iosOption = new BaiduLocationIOSOption();
iosOption.setIsNeedNewVersionRgc(true); // 設定是否需要回傳最新版本rgc資訊
iosOption.setBMKLocationCoordinateType("BMKLocationCoordinateTypeBMK09LL"); // 設定回傳的位置坐標系型別
iosOption.setActivityType("CLActivityTypeAutomotiveNavigation"); // 設定應用位置型別
iosOption.setLocationTimeout(10); // 設定位置獲取超時時間
iosOption.setDesiredAccuracy("kCLLocationAccuracyBest"); // 設定預期精度引數
iosOption.setReGeocodeTimeout(10); // 設定獲取地址資訊超時時間
iosOption.setDistanceFilter(100); // 設定定位最小更新距離
iosOption.setAllowsBackgroundLocationUpdates(true); // 是否允許后臺定位
iosOption.setPauseLocUpdateAutomatically(true); // 定位是否會被系統自動暫停
Map iosMap = iosOption.getMap();
_locationPlugin.prepareLoc(androidMap, iosMap);
}
/// 啟動定位
void _startLocation() {
if (null != _locationPlugin) {
_setLocOption();
_locationPlugin.startLocation();
}
}
五、停止定位
/// 停止定位
void _stopLocation() {
if (null != _locationPlugin) {
_locationPlugin.stopLocation();
}
}
六、動態申請定位權限,并進行監聽
在initState生命周期中,動態申請定位權限,然后對結果進行實時監聽
@override
void initState() {
super.initState();
/// 動態申請定位權限
_locationPlugin.requestPermission();
/// 動態監聽地圖資訊
_locationListener = _locationPlugin.onResultCallback().listen((Map<String, Object>? result){
setState(() {
print('更新了狀態');
if (result != null) {
_loationResult = result;
}
});
});
}
七、移動點定位
// 移動點定位
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.red,
accuracyCircleStrokeColor: Colors.blue,
isAccuracyCircleShow: true,
locationViewImage: 'assets/images/marker_point.png',
locationViewHierarchy: BMFLocationViewHierarchy.LOCATION_VIEW_HIERARCHY_TOP
);
myMapController?.updateLocationViewWithParam(displayParam); // 動態定制我的位置樣式
}
上面的就是所有的步驟了,如果不想看步驟的,可以直接復制下面的代碼,直接進行定位操作
八、全部代碼,可直接復制使用,已添加空安全檢測
地圖中心的經緯度可以手動設定固定值,也可以使用定位產生的變化值,
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/cupertino.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_bmflocation/bdmap_location_flutter_plugin.dart';
import 'package:flutter_bmflocation/flutter_baidu_location.dart';
import 'package:flutter_bmflocation/flutter_baidu_location_android_option.dart';
import 'package:flutter_bmflocation/flutter_baidu_location_ios_option.dart';
//import 'package:flutter_baidu_mapapi_search/flutter_baidu_mapapi_search.dart';
//import 'package:flutter_map_blue/BaiduMapHelper.dart';
class TestBaiduMapPage extends StatefulWidget {
@override
_TestBaiduMapPageState createState() => _TestBaiduMapPageState();
}
class _TestBaiduMapPageState extends State<TestBaiduMapPage> {
var lat,lng;
Map<String, Object>? _loationResult;
BaiduLocation? _baiduLocation; // 定位結果
StreamSubscription<Map<String, Object>?>? _locationListener;// 事件監聽
LocationFlutterPlugin _locationPlugin = new LocationFlutterPlugin();
BMFMapController? myMapController;
var _groupValue; // 權限選項
// 選擇組件
Widget mapTypeSelect() {
return Container(
// width: 500.00,
height: 50.00,
decoration: BoxDecoration(
color: Colors.blue,
),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
///包裹子布局
mainAxisSize: MainAxisSize.max,
children: [
Radio(
///此單選框系結的值 必選引數
value: 'false',
///當前組中這選定的值 必選引數
groupValue: _groupValue,
///點擊狀態改變時的回呼 必選引數
onChanged: (v) {
myMapController?.updateMapOptions(BMFMapOptions(mapType: BMFMapType.Standard));
setState(() {
this._groupValue = v;
});
},
),
Text("普通地圖",style: TextStyle(color: Colors.white))
],
),
Row(
///包裹子布局
mainAxisSize: MainAxisSize.max,
children: [
Radio(
///此單選框系結的值 必選引數
value: 'true',
///當前組中這選定的值 必選引數
groupValue: _groupValue,
///點擊狀態改變時的回呼 必選引數
onChanged: (v) {
myMapController?.updateMapOptions(BMFMapOptions(mapType: BMFMapType.Satellite));
setState(() {
this._groupValue = v;
});
},
),
Text("衛星地圖",style: TextStyle(color: Colors.white))
],
),
]
),
);
}
@override
void initState() {
super.initState();
/// 動態申請定位權限
_locationPlugin.requestPermission();
/// 動態監聽地圖資訊
_locationListener = _locationPlugin.onResultCallback().listen((Map<String, Object>? result){
setState(() {
print('更新了狀態');
if (result != null) {
_loationResult = result;
}
});
});
}
/// 設定android端和ios端定位引數
void _setLocOption() {
/// android 端設定定位引數
BaiduLocationAndroidOption androidOption = new BaiduLocationAndroidOption();
androidOption.setCoorType("bd09ll"); // 設定回傳的位置坐標系型別
androidOption.setIsNeedAltitude(true); // 設定是否需要回傳海拔高度資訊
androidOption.setIsNeedAddres(true); // 設定是否需要回傳地址資訊
androidOption.setIsNeedLocationPoiList(true); // 設定是否需要回傳周邊poi資訊
androidOption.setIsNeedNewVersionRgc(true); // 設定是否需要回傳最新版本rgc資訊
androidOption.setIsNeedLocationDescribe(true); // 設定是否需要回傳位置描述
androidOption.setOpenGps(true); // 設定是否需要使用gps
androidOption.setLocationMode(LocationMode.Hight_Accuracy); // 設定定位模式
androidOption.setScanspan(1000); // 設定發起定位請求時間間隔
Map androidMap = androidOption.getMap();
/// ios 端設定定位引數
BaiduLocationIOSOption iosOption = new BaiduLocationIOSOption();
iosOption.setIsNeedNewVersionRgc(true); // 設定是否需要回傳最新版本rgc資訊
iosOption.setBMKLocationCoordinateType("BMKLocationCoordinateTypeBMK09LL"); // 設定回傳的位置坐標系型別
iosOption.setActivityType("CLActivityTypeAutomotiveNavigation"); // 設定應用位置型別
iosOption.setLocationTimeout(10); // 設定位置獲取超時時間
iosOption.setDesiredAccuracy("kCLLocationAccuracyBest"); // 設定預期精度引數
iosOption.setReGeocodeTimeout(10); // 設定獲取地址資訊超時時間
iosOption.setDistanceFilter(100); // 設定定位最小更新距離
iosOption.setAllowsBackgroundLocationUpdates(true); // 是否允許后臺定位
iosOption.setPauseLocUpdateAutomatically(true); // 定位是否會被系統自動暫停
Map iosMap = iosOption.getMap();
_locationPlugin.prepareLoc(androidMap, iosMap);
}
/// 啟動定位
void _startLocation() {
if (null != _locationPlugin) {
_setLocOption();
_locationPlugin.startLocation();
}
}
/// 停止定位
void _stopLocation() {
if (null != _locationPlugin) {
_locationPlugin.stopLocation();
}
}
void addMarker() {
/// 創建BMFMarker
BMFMarker marker = BMFMarker(
position: BMFCoordinate(自己的經度,自己的緯度),
title: 'flutterMaker',
identifier: 'flutter_marker',
icon: 'assets/images/marker_point.png'
);
/// 添加Marker
myMapController?.addMarker(marker);
}
// 移動點定位
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.red,
accuracyCircleStrokeColor: Colors.blue,
isAccuracyCircleShow: true,
locationViewImage: 'assets/images/marker_point.png',
locationViewHierarchy: BMFLocationViewHierarchy.LOCATION_VIEW_HIERARCHY_TOP
);
myMapController?.updateLocationViewWithParam(displayParam); // 動態定制我的位置樣式
}
/// 創建BMFMarker
BMFMarker marker = BMFMarker(
position: BMFCoordinate(自己的經度,自己的緯度),
title: 'flutterMaker',
identifier: 'flutter_marker',
icon: 'assets/images/BlueTooth.png');
/// 創建完成回呼
void onBMFMapCreated(BMFMapController controller) {
myMapController = controller;
/// 地圖加載回呼
myMapController?.setMapDidLoadCallback(callback: () {
print('mapDidLoad-地圖加載完成!!!');
// addMarker();
});
}
/// 設定地圖引數
BMFMapOptions initMapOptions() {
BMFMapOptions mapOptions = BMFMapOptions(
center: BMFCoordinate(自己的經度,自己的緯度),
zoomLevel: 18,
changeCenterWithDoubleTouchPointEnabled:true,
gesturesEnabled:true ,
scrollEnabled:true ,
zoomEnabled: true ,
rotateEnabled :true,
compassPosition :BMFPoint(0,0) ,
showMapScaleBar:false ,
maxZoomLevel:20,
minZoomLevel:8,
trafficEnabled:true,
);
return mapOptions;
}
Widget _resultWidget(key, value, local) {
return new Container(
height: 20,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text('$key:' ' $value' ' Time:$local',style: TextStyle(color: Colors.white),),
]
),
),
color: Colors.blue,
);
}
@override
Widget build(BuildContext context) {
List<Widget> widgets = []; /// 用來保存位置資訊,然后
if (_loationResult != null) {
widgets.add(_resultWidget(_loationResult?['latitude'], _loationResult?['longitude'],_loationResult?['locTime']));
}
Size screenSize = MediaQuery.of(context).size;
if(_loationResult?['latitude'] != null&&_loationResult?['longitude'] != null){
print('組件重繪');
print(_loationResult?['latitude']);
print(_loationResult?['longitude']);
print(_loationResult?['locTime']);
mapLocation(_loationResult?['latitude'],_loationResult?['longitude']);
}
return Scaffold(
appBar: AppBar(
title: Text("flutter baidu map demo Test"),
),
body:Container(
width: screenSize.width,
height: screenSize.height,
child: Stack(
alignment:Alignment.center , //指定未定位或部分定位widget的對齊方式
children: <Widget>[
Container(
child:BMFMapWidget(
onBMFMapCreated: (controller) { // 創建mapView回呼
onBMFMapCreated(controller);
},
mapOptions: initMapOptions(), // 設定map地圖引數
),
),
Positioned(
top: 0.0,
child: mapTypeSelect(),
),
Positioned(
top: 50,
child:Row(
children: widgets,
),
),
Positioned(
top: 70,
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new RaisedButton(
onPressed: _startLocation,
child: new Text('開始定位'),
color: Colors.blue,
textColor: Colors.white,
),
new Container(width: 20.0),
new RaisedButton(
onPressed: _stopLocation,
child: new Text('停止定位'),
color: Colors.blue,
textColor: Colors.white,
)
],
),
)
],
),
),
);
}
}
九、實作效果
具體的實作效果就如下圖所示,經緯度資訊我給抹掉了,地圖為了防止看到具體定位,我就手動縮小了,

十、總結
上面的代碼是基于空安全檢測的,如果你的sdk版本比較低,不支持空安全檢測的話,只需要將空安全檢測的?去掉,然后通過null來進行檢測就好了,如果大家有什么問題,可以在下面評論,需要源代碼的話可留言,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/301307.html
標籤:其他
