You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1208 lines
48 KiB
1208 lines
48 KiB
import 'dart:convert'; |
|
import 'dart:io'; |
|
import 'dart:ui'; |
|
import 'package:flutter/cupertino.dart'; |
|
import 'package:flutter/material.dart'; |
|
import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'; |
|
import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart'; |
|
import 'package:flutter_baidu_mapapi_search/flutter_baidu_mapapi_search.dart'; |
|
import 'package:flutter_baidu_mapapi_utils/flutter_baidu_mapapi_utils.dart'; |
|
import 'package:flutter_bmflocation/flutter_bmflocation.dart'; |
|
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
|
import 'package:huixiang/utils/flutter_utils.dart'; |
|
import 'package:huixiang/utils/font_weight.dart'; |
|
import 'package:huixiang/utils/location.dart'; |
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
|
import 'package:permission_handler/permission_handler.dart'; |
|
import 'package:url_launcher/url_launcher.dart'; |
|
|
|
import '../generated/l10n.dart'; |
|
import '../retrofit/data/store_info.dart'; |
|
import '../view_widget/custom_image.dart'; |
|
import '../view_widget/location_tips.dart'; |
|
import '../view_widget/round_button.dart'; |
|
|
|
class LocationMap extends StatefulWidget { |
|
final Map<String, dynamic> arguments; |
|
|
|
LocationMap({this.arguments}); |
|
|
|
@override |
|
State<StatefulWidget> createState() { |
|
return _LocationMap(); |
|
} |
|
} |
|
|
|
class _LocationMap extends State<LocationMap> with WidgetsBindingObserver { |
|
StoreInfo storeInfo; |
|
int navigationState = 0; |
|
double distance; |
|
int navigationType = 0; |
|
bool positionSorta = false; |
|
String myAddress; |
|
String myCity; |
|
String hours; |
|
String minutes; |
|
String polylineId; |
|
bool _isShowLocalTips = false; |
|
|
|
@override |
|
void initState() { |
|
super.initState(); |
|
WidgetsBinding.instance.addObserver(this); |
|
storeInfo = widget.arguments["storeInfo"]; |
|
distance = widget.arguments["distance"]; |
|
getLocation(); |
|
} |
|
|
|
void getLocation() async { |
|
bool powerFlag = false; |
|
try { |
|
Future.delayed(Duration(seconds: 5), () { |
|
Location.getInstance().stopLocation(); |
|
}); |
|
powerFlag = await Location.getInstance().startLocation(context, |
|
(BaiduLocation result) { |
|
if (result != null && |
|
result.latitude != null && |
|
result.longitude != null) { |
|
print("location: $result"); |
|
myLatLng = BMFCoordinate(result.latitude, result.longitude); |
|
myAddress = result.locationDetail; |
|
myCity = result.city; |
|
if (distance == null) calculate(); |
|
// AppUtils.coordConvert(myLatLng).then((value) { |
|
// this.myLatLng = value; |
|
locationShow(); |
|
// }); |
|
Location.getInstance().stopLocation(); |
|
} |
|
}); |
|
} finally { |
|
if (!powerFlag) { |
|
if (await Permission.locationWhenInUse.status.isGranted) { |
|
getLocation(); |
|
} else { |
|
_isShowLocalTips = true; |
|
} |
|
// else { |
|
// SmartDialog.showToast("您定位服务未开启,请前往系统设置中开启定位服务", |
|
// alignment: Alignment.center); |
|
// } |
|
} |
|
setState(() {}); |
|
} |
|
} |
|
|
|
calculate() async { |
|
BMFCoordinate bmfCoordinate = BMFCoordinate( |
|
double.tryParse(storeInfo.latitude), |
|
double.tryParse(storeInfo.longitude), |
|
); |
|
distance = double.tryParse( |
|
await AppUtils.calculateDistance(bmfCoordinate, myLatLng, isMi: true)); |
|
} |
|
|
|
locationShow() { |
|
BMFLocation location = BMFLocation( |
|
coordinate: myLatLng, |
|
altitude: 0, |
|
horizontalAccuracy: 5, |
|
verticalAccuracy: -1.0, |
|
speed: -1.0, |
|
course: -1.0, |
|
); |
|
BMFUserLocation userLocation = BMFUserLocation( |
|
location: location, |
|
); |
|
setState(() { |
|
_mapController.updateLocationData(userLocation); |
|
}); |
|
} |
|
|
|
@override |
|
void dispose() { |
|
WidgetsBinding.instance.removeObserver(this); |
|
Location.getInstance().stopLocation(); |
|
super.dispose(); |
|
} |
|
|
|
@override |
|
void didChangeAppLifecycleState(AppLifecycleState state) { |
|
if (state == AppLifecycleState.resumed) { |
|
// 处理应用程序切换回前台的逻辑 |
|
permissionSettings(); |
|
} else if (state == AppLifecycleState.paused) { |
|
// 处理应用程序切换到后台的逻辑 |
|
} |
|
} |
|
|
|
void permissionSettings() async { |
|
if (_isShowLocalTips && await Permission.location.isGranted) { |
|
_isShowLocalTips = false; |
|
getLocation(); |
|
} |
|
} |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return Scaffold( |
|
// appBar: MyAppBar( |
|
// background: Color(0xFFF7F7F7), |
|
// title: widget.arguments["storeName"], |
|
// titleColor: Colors.black87, |
|
// titleSize: 18.sp, |
|
// leadingColor: Colors.black, |
|
// ), |
|
body: Stack( |
|
children: [ |
|
Stack( |
|
children: [ |
|
Column( |
|
children: [ |
|
Expanded( |
|
child: Container( |
|
//BMFMapWidget 组件会自动默认沾满全屏,并且挡住所有遮盖物 ,BMFTextureMapWidget不会强制遮盖其他控件。 |
|
child: (Platform.isAndroid) |
|
? BMFTextureMapWidget( |
|
mapOptions: BMFMapOptions( |
|
center: BMFCoordinate( |
|
double.tryParse(widget.arguments["lat"]), |
|
double.tryParse(widget.arguments["lng"]), |
|
), |
|
showZoomControl: false, |
|
showMapScaleBar: false, |
|
rotateEnabled: false, |
|
zoomLevel: 15, |
|
), |
|
onBMFMapCreated: onMapCreated, |
|
) |
|
: BMFMapWidget( |
|
mapOptions: BMFMapOptions( |
|
center: BMFCoordinate( |
|
double.tryParse(widget.arguments["lat"]), |
|
double.tryParse(widget.arguments["lng"]), |
|
), |
|
showZoomControl: false, |
|
showMapScaleBar: false, |
|
rotateEnabled: false, |
|
zoomLevel: 15, |
|
), |
|
onBMFMapCreated: onMapCreated, |
|
)), |
|
flex: 3, |
|
), |
|
navigationState == 0 |
|
? Container( |
|
height: 253.h, |
|
padding: EdgeInsets.only( |
|
top: 16.h, left: 16.w, right: 28.w), |
|
decoration: BoxDecoration( |
|
color: Colors.white, |
|
boxShadow: [ |
|
BoxShadow( |
|
color: Color(0x08213303), |
|
offset: Offset(0, 2), |
|
blurRadius: 4, |
|
spreadRadius: 0, |
|
), |
|
], |
|
borderRadius: BorderRadius.vertical( |
|
top: Radius.circular(8), |
|
), |
|
), |
|
child: Column( |
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
children: [ |
|
Expanded( |
|
child: Row( |
|
children: [ |
|
Expanded( |
|
child: Column( |
|
children: [ |
|
Text( |
|
storeInfo?.storeName ?? "", |
|
overflow: TextOverflow.ellipsis, |
|
style: TextStyle( |
|
fontSize: 20.sp, |
|
color: Color(0xFF0D0D0D), |
|
fontWeight: MyFontWeight.medium, |
|
), |
|
), |
|
Row( |
|
children: [ |
|
Text( |
|
S.of(context).ren( |
|
storeInfo != null |
|
? storeInfo |
|
.perCapitaConsumption |
|
: "", |
|
), |
|
overflow: TextOverflow.ellipsis, |
|
style: TextStyle( |
|
fontSize: 12.sp, |
|
fontWeight: |
|
MyFontWeight.regular, |
|
color: Color(0xFF4D4D4D), |
|
), |
|
), |
|
SizedBox( |
|
width: 20.w, |
|
), |
|
]..addAll(itemServer( |
|
storeInfo != null |
|
? storeInfo.businessService |
|
: "")), |
|
), |
|
Text( |
|
S.of(context).yingyeshijian(storeInfo == |
|
null |
|
? "" |
|
: (storeInfo.openStartTime == |
|
null && |
|
storeInfo.openEndTime == |
|
null) |
|
? S.of(context).quantian |
|
: "${storeInfo.openStartTime.substring(0, storeInfo.openStartTime.lastIndexOf(":"))} " |
|
"- ${storeInfo.openEndTime.substring(0, storeInfo.openEndTime.lastIndexOf(":"))}"), |
|
style: TextStyle( |
|
color: Color(0xFF4D4D4D), |
|
fontWeight: MyFontWeight.medium, |
|
fontSize: 12.sp, |
|
), |
|
), |
|
], |
|
mainAxisAlignment: |
|
MainAxisAlignment.spaceAround, |
|
crossAxisAlignment: |
|
CrossAxisAlignment.start, |
|
), |
|
), |
|
MImage( |
|
storeInfo != null ? storeInfo.logo : "", |
|
width: 72.h, |
|
height: 72.h, |
|
fit: BoxFit.cover, |
|
errorSrc: "assets/image/default_1.webp", |
|
fadeSrc: "assets/image/default_1.webp", |
|
), |
|
], |
|
), |
|
), |
|
Padding( |
|
padding: EdgeInsets.only(bottom: 32.h), |
|
child: Text( |
|
"${storeInfo != null ? storeInfo.address : ""}", |
|
maxLines: 2, |
|
textAlign: TextAlign.justify, |
|
style: TextStyle( |
|
color: Color(0xFF353535), |
|
fontWeight: MyFontWeight.regular, |
|
fontSize: 12.sp, |
|
), |
|
), |
|
), |
|
GestureDetector( |
|
behavior: HitTestBehavior.opaque, |
|
onTap: () { |
|
if (myLatLng == null) { |
|
// onOpenBaiduMap(); |
|
SmartDialog.showToast( |
|
"您定位服务未开启,请前往系统设置中开启定位服务", |
|
alignment: Alignment.center); |
|
} else { |
|
navigationState = 1; |
|
if ((distance ?? 0) < 500) |
|
navigationType = 1; |
|
else if ((distance ?? 0) < 1500) |
|
navigationType = 2; |
|
else |
|
navigationType = 4; |
|
navigationPosition(); |
|
} |
|
}, |
|
child: Container( |
|
alignment: Alignment.center, |
|
width: double.infinity, |
|
padding: EdgeInsets.symmetric(vertical: 10.h), |
|
margin: EdgeInsets.only(bottom: 30.h), |
|
decoration: BoxDecoration( |
|
color: Color(0xFF32A060), |
|
borderRadius: BorderRadius.circular(23), |
|
), |
|
child: Text( |
|
"到这去", |
|
style: TextStyle( |
|
fontSize: 20.sp, |
|
color: Colors.white, |
|
fontWeight: MyFontWeight.medium, |
|
), |
|
), |
|
), |
|
) |
|
], |
|
), |
|
) |
|
: navigationDistance(), |
|
], |
|
), |
|
navigationState == 0 |
|
? GestureDetector( |
|
behavior: HitTestBehavior.opaque, |
|
onTap: () { |
|
Navigator.of(context).pop(); |
|
}, |
|
child: Container( |
|
height: 56.h, |
|
margin: EdgeInsets.only( |
|
top: MediaQuery.of(context).padding.top + 16.h, |
|
left: 14.w, |
|
right: 14.w), |
|
padding: EdgeInsets.only(left: 12.w, right: 21.w), |
|
decoration: BoxDecoration( |
|
color: Colors.white, |
|
boxShadow: [ |
|
BoxShadow( |
|
color: Color(0x08213303), |
|
offset: Offset(0, 2), |
|
blurRadius: 4, |
|
spreadRadius: 0, |
|
), |
|
], |
|
borderRadius: BorderRadius.circular(6), |
|
), |
|
child: Row( |
|
children: [ |
|
Icon( |
|
Icons.arrow_back_ios, |
|
color: Color(0xFF353535), |
|
size: 24, |
|
), |
|
Expanded( |
|
child: Text( |
|
storeInfo?.storeName ?? "", |
|
overflow: TextOverflow.ellipsis, |
|
style: TextStyle( |
|
color: Color(0xFF0D0D0D), |
|
fontSize: 18.sp, |
|
fontWeight: MyFontWeight.regular, |
|
), |
|
)) |
|
], |
|
), |
|
), |
|
) |
|
: navigationBox(), |
|
], |
|
), |
|
if (_isShowLocalTips) |
|
Padding( |
|
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), |
|
child: LocationTips(() { |
|
setState(() { |
|
_isShowLocalTips = false; |
|
}); |
|
}), |
|
) |
|
], |
|
), |
|
); |
|
} |
|
|
|
void onOpenBaiduMap() async { |
|
launch( |
|
"baidumap://map/marker?location=${storeInfo.latitude},${storeInfo.longitude}&title=${storeInfo.storeName}&content=${storeInfo.storeName}&traffic=on&src=andr.baidu.openAPIdemo&coord_type=gcj02"); |
|
} |
|
|
|
//調取百度地圖APP |
|
void onOpenBaiduMapRoute() async { |
|
// 我的位置 |
|
BMFCoordinate startCoord = BMFCoordinate( |
|
positionSorta == false |
|
? myLatLng.latitude |
|
: latLng.latitude, |
|
positionSorta == false |
|
? myLatLng.longitude |
|
: latLng.longitude); |
|
String startName = ((positionSorta == false) ? "我的位置" : "终点"); |
|
// 去的位置 |
|
String endName = ((positionSorta == false) ? "终点" : "我的位置"); |
|
BMFCoordinate endCoord = BMFCoordinate( |
|
positionSorta == false |
|
? latLng.latitude |
|
: myLatLng.latitude, |
|
positionSorta == false |
|
? latLng.longitude |
|
: myLatLng.longitude); |
|
BMFOpenRouteOption routeOption = BMFOpenRouteOption( |
|
startCoord: startCoord, |
|
startName: startName, |
|
endCoord: endCoord, |
|
endName: endName, |
|
routeType: navigationType == 1 |
|
? BMFOpenRouteType.WalkingRoute |
|
: navigationType == 2 |
|
? BMFOpenRouteType.WalkingRoute |
|
: navigationType == 3 |
|
? BMFOpenRouteType.TransitRoute |
|
: BMFOpenRouteType.DrivingRoute, |
|
appScheme: 'baidumapsdk_flutter://mapsdk.baidu.com', |
|
// 指定返回自定义scheme |
|
isSupportWeb: true); |
|
BMFOpenErrorCode flag = |
|
await BMFOpenMapUtils.openBaiduMapRoute(routeOption); |
|
print('open - route - errorCode = $flag'); |
|
} |
|
|
|
updateMapLine(List<BMFCoordinate> coordinates, int needHours, int needMinutes, |
|
double needDistance) { |
|
try { |
|
//刪除之前的創建的點和綫 |
|
_mapController.cleanAllMarkers(); |
|
if (polylineId != null) _mapController.removeOverlay(polylineId); |
|
|
|
/// 创建polyline |
|
BMFPolyline colorsPolyline = BMFPolyline( |
|
// id: polylineOptions.hashCode.toString(), |
|
coordinates: coordinates, |
|
indexs: [0], |
|
textures: [ |
|
navigationType != 4 |
|
? 'assets/image/traffic_texture_unknown.png' |
|
: 'assets/image/traffic_texture_smooth.png' |
|
], |
|
width: Platform.isAndroid ? 16 : 10, |
|
lineDashType: BMFLineDashType.LineDashTypeNone, |
|
lineCapType: BMFLineCapType.LineCapButt, |
|
lineJoinType: BMFLineJoinType.LineJoinRound); |
|
polylineId = colorsPolyline.id; |
|
|
|
/// 添加polyline |
|
_mapController.addPolyline(colorsPolyline); |
|
var startBmfMarker = BMFMarker.icon( |
|
position: BMFCoordinate( |
|
coordinates.first.latitude, coordinates.first.longitude), |
|
centerOffset: BMFPoint(0.5, 0.7), |
|
enabled: false, |
|
icon: "assets/image/icon_start.png", |
|
draggable: false, |
|
); |
|
_mapController.addMarker(startBmfMarker); |
|
|
|
var terminalBmfMarker = BMFMarker.icon( |
|
position: BMFCoordinate( |
|
coordinates.last.latitude, coordinates.last.longitude), |
|
centerOffset: BMFPoint(0.5, 0.7), |
|
enabled: false, |
|
icon: "assets/image/icon_end.png", |
|
draggable: false, |
|
); |
|
_mapController.addMarker(terminalBmfMarker); |
|
|
|
double maxLatitude = 0, |
|
minLatitude = 0, |
|
maxLongitude = 0, |
|
minLongitude = 0; |
|
coordinates.forEach((element) { |
|
if (element.latitude > maxLatitude) maxLatitude = element.latitude; |
|
if (minLatitude == 0) |
|
minLatitude = element.latitude; |
|
else if (element.latitude < minLatitude) minLatitude = element.latitude; |
|
|
|
if (element.longitude > maxLongitude) maxLongitude = element.longitude; |
|
if (minLongitude == 0) |
|
minLongitude = element.longitude; |
|
else if (element.longitude < minLongitude) |
|
minLongitude = element.longitude; |
|
}); |
|
_mapController.setVisibleMapBounds( |
|
BMFCoordinateBounds( |
|
northeast: BMFCoordinate( |
|
maxLatitude + ((maxLatitude - minLatitude) * 0.8), |
|
maxLongitude + ((maxLongitude - minLongitude) / 2)), |
|
southwest: BMFCoordinate( |
|
minLatitude - ((maxLatitude - minLatitude) * 0.2), |
|
minLongitude - ((maxLongitude - minLongitude) / 2))), |
|
true); |
|
|
|
hours = needHours == 0 ? "" : "$needHours小时"; |
|
minutes = needMinutes == 0 ? "" : "$needMinutes分钟"; |
|
distance = needDistance; |
|
} finally { |
|
setState(() {}); |
|
EasyLoading.dismiss(); |
|
} |
|
} |
|
|
|
navigationPosition() async { |
|
EasyLoading.show( |
|
status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); |
|
BMFPlanNode from = BMFPlanNode( |
|
cityName: positionSorta == false ? myCity : (storeInfo?.city ?? ""), |
|
name: positionSorta == false ? myAddress : storeInfo?.address ?? "", |
|
pt: positionSorta == false |
|
? BMFCoordinate(myLatLng?.latitude ?? 0, myLatLng?.longitude ?? 0) |
|
: latLng); |
|
BMFPlanNode to = BMFPlanNode( |
|
// cityName: positionSorta == false ? (storeInfo?.city ?? "") : myCity, |
|
// name: positionSorta == false ? (storeInfo?.address ?? "") : myAddress, |
|
pt: positionSorta == false |
|
? latLng |
|
: BMFCoordinate(myLatLng?.latitude ?? 0, myLatLng?.longitude ?? 0)); |
|
if (navigationType == 1) { |
|
//步行 |
|
BMFWalkingRoutePlanOption walkingRoutePlanOption = |
|
BMFWalkingRoutePlanOption(from: from, to: to); |
|
// 检索实例 |
|
BMFWalkingRouteSearch walkingRouteSearch = BMFWalkingRouteSearch(); |
|
// 检索回调 |
|
walkingRouteSearch.onGetWalkingRouteSearchResult(callback: |
|
(BMFWalkingRouteResult result, BMFSearchErrorCode errorCode) async { |
|
if (errorCode == BMFSearchErrorCode.RESULT_NOT_FOUND) { |
|
SmartDialog.showToast("该方案暂无可用的规划路线", alignment: Alignment.center); |
|
EasyLoading.dismiss(); |
|
return; |
|
} else if (errorCode != BMFSearchErrorCode.NO_ERROR) { |
|
SmartDialog.showToast("获取路线规划失败,请稍后再试", alignment: Alignment.center); |
|
EasyLoading.dismiss(); |
|
return; |
|
} |
|
print( |
|
'`步行检索回调 errorCode = ${errorCode} \n result = ${result?.toMap()}'); |
|
|
|
/// 坐标点 |
|
List<BMFCoordinate> coordinates = []; |
|
result.routes.first.steps.forEach((e1) { |
|
e1.points.forEach((e2) { |
|
coordinates.add(BMFCoordinate(e2.latitude, e2.longitude)); |
|
}); |
|
}); |
|
updateMapLine( |
|
coordinates, |
|
result.routes.first.duration.hours, |
|
result.routes.first.duration.minutes, |
|
result.routes.first.distance.toDouble()); |
|
}); |
|
bool flag = |
|
await walkingRouteSearch.walkingRouteSearch(walkingRoutePlanOption); |
|
} else if (navigationType == 2) { |
|
//骑行 |
|
BMFRidingRoutePlanOption ridingRoutePlanOption = |
|
BMFRidingRoutePlanOption(from: from, to: to); |
|
BMFRidingRouteSearch ridingRouteSearch = BMFRidingRouteSearch(); |
|
ridingRouteSearch.onGetRidingRouteSearchResult(callback: |
|
(BMFRidingRouteResult result, BMFSearchErrorCode errorCode) { |
|
if (errorCode == BMFSearchErrorCode.RESULT_NOT_FOUND) { |
|
SmartDialog.showToast("该方案暂无可用的规划路线", alignment: Alignment.center); |
|
EasyLoading.dismiss(); |
|
return; |
|
} else if (errorCode != BMFSearchErrorCode.NO_ERROR) { |
|
SmartDialog.showToast("获取路线规划失败,请稍后再试", alignment: Alignment.center); |
|
EasyLoading.dismiss(); |
|
return; |
|
} |
|
print( |
|
'`骑行检索回调 errorCode = ${errorCode} \n result = ${result?.toMap()}'); |
|
|
|
/// 坐标点 |
|
List<BMFCoordinate> coordinates = []; |
|
result.routes.first.steps.forEach((e1) { |
|
e1.points.forEach((e2) { |
|
coordinates.add(BMFCoordinate(e2.latitude, e2.longitude)); |
|
}); |
|
}); |
|
updateMapLine( |
|
coordinates, |
|
result.routes.first.duration.hours, |
|
result.routes.first.duration.minutes, |
|
result.routes.first.distance.toDouble()); |
|
}); |
|
// 发起检索 |
|
bool flag = |
|
await ridingRouteSearch.ridingRouteSearch(ridingRoutePlanOption); |
|
} else if (navigationType == 3) { |
|
//公交 |
|
BMFTransitRoutePlanOption transitRoutePlanOption = |
|
BMFTransitRoutePlanOption(from: from, to: to, city: '武汉市'); |
|
BMFTransitRouteSearch transitRouteSearch = BMFTransitRouteSearch(); |
|
transitRouteSearch.onGetTransitRouteSearchResult(callback: |
|
(BMFTransitRouteResult result, BMFSearchErrorCode errorCode) { |
|
if (errorCode == BMFSearchErrorCode.RESULT_NOT_FOUND) { |
|
SmartDialog.showToast("该方案暂无可用的规划路线", alignment: Alignment.center); |
|
EasyLoading.dismiss(); |
|
return; |
|
} else if (errorCode != BMFSearchErrorCode.NO_ERROR) { |
|
SmartDialog.showToast("获取路线规划失败,请稍后再试", alignment: Alignment.center); |
|
EasyLoading.dismiss(); |
|
return; |
|
} |
|
print( |
|
'`市内公交检索回调 errorCode = ${errorCode} \n result = ${result?.toMap()}'); |
|
|
|
/// 坐标点 |
|
List<BMFCoordinate> coordinates = []; |
|
result.routes.first.steps.forEach((e1) { |
|
e1.points.forEach((e2) { |
|
coordinates.add(BMFCoordinate(e2.latitude, e2.longitude)); |
|
}); |
|
}); |
|
updateMapLine( |
|
coordinates, |
|
result.routes.first.duration.hours, |
|
result.routes.first.duration.minutes, |
|
result.routes.first.distance.toDouble()); |
|
}); |
|
// 发起检索 |
|
bool flag = |
|
await transitRouteSearch.transitRouteSearch(transitRoutePlanOption); |
|
} else { |
|
//驾车 |
|
BMFDrivingRoutePlanOption drivingRoutePlanOption = |
|
BMFDrivingRoutePlanOption(from: from, to: to); |
|
BMFDrivingRouteSearch drivingRouteSearch = BMFDrivingRouteSearch(); |
|
drivingRouteSearch.onGetDrivingRouteSearchResult(callback: |
|
(BMFDrivingRouteResult result, BMFSearchErrorCode errorCode) { |
|
if (errorCode == BMFSearchErrorCode.RESULT_NOT_FOUND) { |
|
SmartDialog.showToast("该方案暂无可用的规划路线", alignment: Alignment.center); |
|
EasyLoading.dismiss(); |
|
return; |
|
} else if (errorCode != BMFSearchErrorCode.NO_ERROR) { |
|
SmartDialog.showToast("获取路线规划失败,请稍后再试", alignment: Alignment.center); |
|
EasyLoading.dismiss(); |
|
return; |
|
} |
|
print( |
|
'驾车检索回调 errorCode = ${errorCode} \n result = ${result?.toMap()}'); |
|
|
|
/// 坐标点 |
|
List<BMFCoordinate> coordinates = []; |
|
result.routes.first.steps.forEach((e1) { |
|
e1.points.forEach((e2) { |
|
coordinates.add(BMFCoordinate(e2.latitude, e2.longitude)); |
|
}); |
|
}); |
|
updateMapLine( |
|
coordinates, |
|
result.routes.first.duration.hours, |
|
result.routes.first.duration.minutes, |
|
result.routes.first.distance.toDouble()); |
|
}); |
|
// 发起检索 |
|
bool flag = |
|
await drivingRouteSearch.dringRouteSearch(drivingRoutePlanOption); |
|
} |
|
} |
|
|
|
Widget navigationBox() { |
|
return Container( |
|
height: 132.h, |
|
margin: EdgeInsets.only( |
|
top: MediaQuery.of(context).padding.top + 16.h, |
|
left: 14.w, |
|
right: 14.w), |
|
padding: EdgeInsets.only(left: 12.w, right: 18.w, top: 8.h), |
|
decoration: BoxDecoration( |
|
color: Colors.white, |
|
boxShadow: [ |
|
BoxShadow( |
|
color: Color(0x08213303), |
|
offset: Offset(0, 2), |
|
blurRadius: 4, |
|
spreadRadius: 0, |
|
), |
|
], |
|
borderRadius: BorderRadius.circular(6), |
|
), |
|
child: Row( |
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
children: [ |
|
GestureDetector( |
|
behavior: HitTestBehavior.opaque, |
|
onTap: () { |
|
setState(() { |
|
navigationState = 0; |
|
}); |
|
}, |
|
child: Padding( |
|
padding: EdgeInsets.only(top: 10.h, right: 10.w), |
|
child: Icon( |
|
Icons.arrow_back_ios, |
|
color: Color(0xFF353535), |
|
size: 24, |
|
), |
|
), |
|
), |
|
Expanded( |
|
child: Column( |
|
children: [ |
|
Container( |
|
width: double.infinity, |
|
decoration: BoxDecoration( |
|
color: Color(0xFFF5F5F5), |
|
borderRadius: BorderRadius.circular(6), |
|
), |
|
padding: EdgeInsets.only( |
|
top: 12.h, |
|
bottom: 12.h, |
|
left: 15.w, |
|
), |
|
child: Row( |
|
mainAxisAlignment: MainAxisAlignment.center, |
|
children: [ |
|
Expanded( |
|
child: Column( |
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
children: [ |
|
Padding( |
|
padding: EdgeInsets.only( |
|
bottom: 14.h, |
|
), |
|
child: Row( |
|
children: [ |
|
Container( |
|
width: 4.h, |
|
height: 4.h, |
|
margin: EdgeInsets.only(right: 20.w), |
|
decoration: BoxDecoration( |
|
color: Color(0xFF32A060), |
|
borderRadius: BorderRadius.circular(6), |
|
), |
|
), |
|
Expanded( |
|
child: Text( |
|
positionSorta == false |
|
? "我的位置" |
|
: (storeInfo?.storeName ?? ""), |
|
overflow: TextOverflow.ellipsis, |
|
style: TextStyle( |
|
color: Color(0xFF0D0D0D), |
|
fontSize: 14.sp, |
|
fontWeight: MyFontWeight.semi_bold, |
|
), |
|
)) |
|
], |
|
), |
|
), |
|
Row( |
|
children: [ |
|
Container( |
|
width: 4.h, |
|
height: 4.h, |
|
margin: EdgeInsets.only(right: 20.w), |
|
decoration: BoxDecoration( |
|
color: Color(0xFFFA5151), |
|
borderRadius: BorderRadius.circular(6), |
|
), |
|
), |
|
Expanded( |
|
child: Text( |
|
positionSorta == false |
|
? (storeInfo?.storeName ?? "") |
|
: "我的位置", |
|
overflow: TextOverflow.ellipsis, |
|
style: TextStyle( |
|
color: Color(0xFF0D0D0D), |
|
fontSize: 14.sp, |
|
fontWeight: MyFontWeight.semi_bold, |
|
), |
|
)) |
|
], |
|
) |
|
], |
|
)), |
|
GestureDetector( |
|
behavior: HitTestBehavior.opaque, |
|
onTap: () { |
|
positionSorta = !positionSorta; |
|
navigationPosition(); |
|
}, |
|
child: Container( |
|
padding: EdgeInsets.only(right: 24.w), |
|
child: Image.asset( |
|
"assets/image/position_sort.webp", |
|
fit: BoxFit.fill, |
|
height: 16.h, |
|
width: 14.w, |
|
), |
|
), |
|
) |
|
], |
|
), |
|
), |
|
SizedBox( |
|
height: 12.h, |
|
), |
|
Row( |
|
children: [ |
|
Expanded( |
|
child: GestureDetector( |
|
behavior: HitTestBehavior.opaque, |
|
onTap: () { |
|
navigationType = 4; |
|
navigationPosition(); |
|
}, |
|
child: Container( |
|
decoration: BoxDecoration( |
|
color: navigationType == 4 |
|
? Color(0xFFE8FFF2) |
|
: Colors.transparent, |
|
borderRadius: BorderRadius.circular(23), |
|
), |
|
padding: |
|
EdgeInsets.symmetric(vertical: 5.h, horizontal: 13.w), |
|
child: Row( |
|
children: [ |
|
if (navigationType == 4) |
|
Image.asset( |
|
"assets/image/icon_drive.webp", |
|
fit: BoxFit.fill, |
|
height: 16.h, |
|
width: 14.w, |
|
), |
|
Padding( |
|
padding: EdgeInsets.only(left: 2.w), |
|
child: Text( |
|
"驾车", |
|
overflow: TextOverflow.ellipsis, |
|
style: TextStyle( |
|
color: navigationType == 4 |
|
? Color(0xFF32A060) |
|
: Colors.black, |
|
fontSize: 12.sp, |
|
fontWeight: MyFontWeight.medium, |
|
), |
|
), |
|
) |
|
], |
|
), |
|
), |
|
)), |
|
Expanded( |
|
child: GestureDetector( |
|
behavior: HitTestBehavior.opaque, |
|
onTap: () { |
|
navigationType = 3; |
|
navigationPosition(); |
|
}, |
|
child: Container( |
|
decoration: BoxDecoration( |
|
color: navigationType == 3 |
|
? Color(0xFFE8FFF2) |
|
: Colors.transparent, |
|
borderRadius: BorderRadius.circular(23), |
|
), |
|
padding: EdgeInsets.symmetric( |
|
vertical: 5.h, horizontal: 13.w), |
|
child: Row( |
|
children: [ |
|
if (navigationType == 3) |
|
Image.asset( |
|
"assets/image/icon_transit.webp", |
|
fit: BoxFit.fill, |
|
height: 16.h, |
|
width: 14.w, |
|
), |
|
Padding( |
|
padding: EdgeInsets.only(left: 2.w), |
|
child: Text( |
|
"公交", |
|
overflow: TextOverflow.ellipsis, |
|
style: TextStyle( |
|
color: navigationType == 3 |
|
? Color(0xFF32A060) |
|
: Colors.black, |
|
fontSize: 12.sp, |
|
fontWeight: MyFontWeight.medium, |
|
), |
|
), |
|
) |
|
], |
|
), |
|
))), |
|
Expanded( |
|
child: GestureDetector( |
|
behavior: HitTestBehavior.opaque, |
|
onTap: () { |
|
navigationType = 2; |
|
navigationPosition(); |
|
}, |
|
child: Container( |
|
decoration: BoxDecoration( |
|
color: navigationType == 2 |
|
? Color(0xFFE8FFF2) |
|
: Colors.transparent, |
|
borderRadius: BorderRadius.circular(23), |
|
), |
|
padding: EdgeInsets.symmetric( |
|
vertical: 5.h, horizontal: 13.w), |
|
child: Row( |
|
children: [ |
|
if (navigationType == 2) |
|
Image.asset( |
|
"assets/image/icon_by_bike.webp", |
|
fit: BoxFit.fill, |
|
height: 16.h, |
|
width: 14.w, |
|
), |
|
Padding( |
|
padding: EdgeInsets.only(left: 2.w), |
|
child: Text( |
|
"骑行", |
|
overflow: TextOverflow.ellipsis, |
|
style: TextStyle( |
|
color: navigationType == 2 |
|
? Color(0xFF32A060) |
|
: Colors.black, |
|
fontSize: 12.sp, |
|
fontWeight: MyFontWeight.medium, |
|
), |
|
), |
|
) |
|
], |
|
), |
|
))), |
|
Expanded( |
|
child: GestureDetector( |
|
behavior: HitTestBehavior.opaque, |
|
onTap: () { |
|
navigationType = 1; |
|
navigationPosition(); |
|
}, |
|
child: Container( |
|
decoration: BoxDecoration( |
|
color: navigationType == 1 |
|
? Color(0xFFE8FFF2) |
|
: Colors.transparent, |
|
borderRadius: BorderRadius.circular(23), |
|
), |
|
padding: EdgeInsets.symmetric( |
|
vertical: 5.h, horizontal: 13.w), |
|
child: Row( |
|
children: [ |
|
if (navigationType == 1) |
|
Image.asset( |
|
"assets/image/icon_walk.webp", |
|
fit: BoxFit.fill, |
|
height: 16.h, |
|
width: 14.w, |
|
), |
|
Padding( |
|
padding: EdgeInsets.only(left: 2.w), |
|
child: Text( |
|
"步行", |
|
overflow: TextOverflow.ellipsis, |
|
style: TextStyle( |
|
color: navigationType == 1 |
|
? Color(0xFF32A060) |
|
: Colors.black, |
|
fontSize: 12.sp, |
|
fontWeight: MyFontWeight.medium, |
|
), |
|
), |
|
) |
|
], |
|
), |
|
))), |
|
], |
|
) |
|
], |
|
)) |
|
], |
|
), |
|
); |
|
} |
|
|
|
Widget navigationDistance() { |
|
return Container( |
|
height: 173.h, |
|
padding: EdgeInsets.only(top: 16.h, left: 16.w, right: 16.w), |
|
decoration: BoxDecoration( |
|
color: Colors.white, |
|
boxShadow: [ |
|
BoxShadow( |
|
color: Color(0x08213303), |
|
offset: Offset(0, 2), |
|
blurRadius: 4, |
|
spreadRadius: 0, |
|
), |
|
], |
|
borderRadius: BorderRadius.vertical( |
|
top: Radius.circular(8), |
|
), |
|
), |
|
child: Column( |
|
// mainAxisAlignment: MainAxisAlignment.start, |
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
children: [ |
|
Expanded( |
|
child: Row( |
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
children: [ |
|
Text( |
|
"${navigationType == 1 ? "步行" : navigationType == 2 ? "骑行" : navigationType == 3 ? "公交" : "驾车"}${(hours ?? "") + (minutes ?? "")}", |
|
overflow: TextOverflow.ellipsis, |
|
style: TextStyle( |
|
fontSize: 20.sp, |
|
color: Color(0xFF0D0D0D), |
|
fontWeight: MyFontWeight.bold, |
|
), |
|
), |
|
Padding( |
|
padding: EdgeInsets.only(left: 40.w), |
|
child: Text( |
|
(distance ?? 0) > 1000 |
|
? S.of(context).gongli( |
|
((distance ?? 0) / 1000 * 100).toInt() / 100.0) |
|
: S |
|
.of(context) |
|
.mi(((distance ?? 0) * 100).toInt() / 100.0), |
|
overflow: TextOverflow.ellipsis, |
|
style: TextStyle( |
|
fontSize: 20.sp, |
|
color: Color(0xFF0D0D0D), |
|
fontWeight: MyFontWeight.bold, |
|
), |
|
), |
|
), |
|
], |
|
), |
|
), |
|
GestureDetector( |
|
behavior: HitTestBehavior.opaque, |
|
onTap: () { |
|
setState(() { |
|
navigationState = 1; |
|
showMapSelect(); |
|
}); |
|
}, |
|
child: Container( |
|
alignment: Alignment.center, |
|
width: double.infinity, |
|
padding: EdgeInsets.symmetric(vertical: 10.h), |
|
margin: EdgeInsets.only(bottom: 30.h), |
|
decoration: BoxDecoration( |
|
color: Color(0xFF32A060), |
|
borderRadius: BorderRadius.circular(23), |
|
), |
|
child: Text( |
|
navigationType == 1 |
|
? "步行导航" |
|
: navigationType == 2 |
|
? "骑行导航" |
|
: navigationType == 3 |
|
? "公交导航" |
|
: "驾车导航", |
|
style: TextStyle( |
|
fontSize: 20.sp, |
|
color: Colors.white, |
|
fontWeight: MyFontWeight.medium, |
|
), |
|
), |
|
), |
|
) |
|
], |
|
), |
|
); |
|
} |
|
|
|
showMapSelect() { |
|
showCupertinoModalPopup( |
|
context: context, |
|
builder: (context) { |
|
return CupertinoActionSheet( |
|
actions: [ |
|
CupertinoActionSheetAction( |
|
child: Text( |
|
"百度地图", |
|
style: TextStyle( |
|
fontWeight: MyFontWeight.regular, |
|
), |
|
), |
|
onPressed: () { |
|
onOpenBaiduMapRoute(); |
|
Navigator.of(context).pop(); |
|
}, |
|
isDefaultAction: true, |
|
isDestructiveAction: false, |
|
), |
|
], |
|
cancelButton: CupertinoActionSheetAction( |
|
onPressed: () { |
|
Navigator.of(context).pop(); |
|
}, |
|
child: Text(S.of(context).quxiao, |
|
style: TextStyle( |
|
color: Colors.blue, |
|
),), |
|
isDestructiveAction: true, |
|
), |
|
); |
|
}); |
|
} |
|
|
|
List<Widget> itemServer(String businessService) { |
|
if (businessService == null || businessService == "") return []; |
|
var list = businessService.split(","); |
|
return list |
|
.map((e) => Container( |
|
margin: EdgeInsets.only(right: 8.w), |
|
child: RoundButton( |
|
height: 17.h * AppUtils.textScale(context), |
|
text: "$e", |
|
backgroup: Color(0xFFFF7A1A), |
|
padding: EdgeInsets.only( |
|
left: 2.w, |
|
right: 2.w, |
|
), |
|
fontSize: 10.sp, |
|
textColor: Colors.white, |
|
), |
|
)) |
|
.toList(); |
|
} |
|
|
|
BMFMapController _mapController; |
|
BMFCoordinate latLng; |
|
BMFCoordinate myLatLng; |
|
BMFMarker bmfMarker; |
|
|
|
onMapCreated(BMFMapController controller) { |
|
_mapController = controller; |
|
setState(() { |
|
_mapController.showUserLocation(true); |
|
_mapController.setCustomMapStyle('assets/map_style/chatian.sty', 0); |
|
BMFUserLocationDisplayParam displayParam = BMFUserLocationDisplayParam( |
|
locationViewOffsetX: 0, |
|
locationViewOffsetY: 0, |
|
accuracyCircleFillColor: Colors.red, |
|
accuracyCircleStrokeColor: Colors.blue, |
|
isAccuracyCircleShow: true, |
|
locationViewImage: 'assets/image/icon_my_location.webp', |
|
locationViewHierarchy: |
|
BMFLocationViewHierarchy.LOCATION_VIEW_HIERARCHY_BOTTOM, |
|
); |
|
_mapController.updateLocationViewWithParam(displayParam); |
|
addMarker(); |
|
}); |
|
} |
|
|
|
addMarker() async { |
|
latLng = await AppUtils.coordConvert(BMFCoordinate(double.tryParse(widget.arguments["lat"]), |
|
double.tryParse(widget.arguments["lng"]))); |
|
// latLng = BMFCoordinate(double.tryParse(widget.arguments["lat"]), |
|
// double.tryParse(widget.arguments["lng"])); |
|
|
|
if (bmfMarker == null && _mapController != null) { |
|
bmfMarker = BMFMarker.icon( |
|
position: latLng, |
|
centerOffset: BMFPoint(0.5, 0.7), |
|
enabled: false, |
|
icon: "assets/image/icon_map_marker.webp", |
|
draggable: false, |
|
); |
|
_mapController.addMarker(bmfMarker); |
|
} |
|
_mapController.setCenterCoordinate(latLng, true); |
|
} |
|
}
|
|
|