调整地图样式

This commit is contained in:
2025-11-27 15:25:58 +08:00
parent aa30d13b91
commit da4149ec60
3 changed files with 384 additions and 263 deletions

View File

@@ -4,124 +4,133 @@ import 'dart:convert';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:geolocator/geolocator.dart';
import 'package:getx_scaffold/getx_scaffold.dart';
import 'package:permission_handler/permission_handler.dart'; // 确保引用这个做权限请求
import 'package:permission_handler/permission_handler.dart';
class MapController extends GetxController with BaseControllerMixin {
class MapController extends GetxController with BaseControllerMixin ,WidgetsBindingObserver{
@override
String get builderId => 'map';
InAppWebViewController? webViewController;
StreamSubscription<Position>? positionStream;
final RxBool isLocationPermissionGranted = false.obs;
// 缓存最后一次的位置,防止 WebView 加载慢于定位
// --- 状态标志 ---
final RxBool isLocationPermissionGranted = false.obs;
final RxBool isMapReady = false.obs; // 跟踪地图是否加载完成
Position? _lastKnownPosition;
// 是否已经初始化过地图中心
bool _hasInitializedMapCenter = false;
@override
void onInit() {
super.onInit();
WidgetsBinding.instance.addObserver(this); // 注册监听
requestLocationPermission();
}
@override
void onClose() {
WidgetsBinding.instance.removeObserver(this); // 移除监听
positionStream?.cancel();
super.onClose();
}
// 请求权限
void requestLocationPermission() async {
var status = await Permission.locationWhenInUse.request();
print("权限状态: $status"); // 在控制台看这个输出
if (status.isGranted) {
isLocationPermissionGranted.value = true;
showToast('定位权限已获取');
_startLocationTracking();
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
// 回到前台,如果之前有权限且开启过,恢复定位
if(isLocationPermissionGranted.value) _startLocationTracking();
} else if (state == AppLifecycleState.paused) {
// 切到后台,取消定位流
positionStream?.cancel();
}
else if (status.isPermanentlyDenied) {
// iOS 特性:如果你之前点过“不允许”,之后再请求都会直接进这里
isLocationPermissionGranted.value = false;
// 引导用户去设置页面开启
openAppSettings();
}
else {
// 第一次被拒绝,或者其他情况
isLocationPermissionGranted.value = false;
showErrorToast('需要定位权限才能显示您的位置');
}
}
// 开启定位监听
void _startLocationTracking() async {
// 再次检查服务是否开启
/// WebView 创建完成时调用
void onWebViewCreated(InAppWebViewController controller) {
webViewController = controller;
// 添加 JS Handler 来监听来自网页的 'mapReady' 事件
controller.addJavaScriptHandler(
handlerName: 'mapReady',
callback: (args) {
print("Flutter<-JS: Map is ready, starting location tracking.");
isMapReady.value = true;
// 地图就绪后,如果已有权限和缓存的定位,则开始定位
if (isLocationPermissionGranted.value) {
_startLocationTracking();
}
},
);
}
/// 优化后的权限请求函数
void requestLocationPermission() async {
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
showErrorToast('请开启手机的定位服务');
return;
}
var status = await Permission.locationWhenInUse.request();
switch (status) {
case PermissionStatus.granted:
isLocationPermissionGranted.value = true;
// 权限已获取,如果地图也已就绪,则开始定位
if (isMapReady.value) {
_startLocationTracking();
}
break;
case PermissionStatus.denied:
showErrorToast('需要定位权限才能显示您的位置');
break;
case PermissionStatus.permanentlyDenied:
showErrorToast('定位权限已被永久拒绝,请到设置中手动开启');
openAppSettings();
break;
default:
showErrorToast('获取定位权限时发生未知错误');
break;
}
}
/// 开始定位监听 (不再需要 delay)
void _startLocationTracking() async {
if (!isLocationPermissionGranted.value ||
!await Geolocator.isLocationServiceEnabled()) {
return;
}
const LocationSettings locationSettings = LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 50, // 移动更新范围
distanceFilter: 10,
);
// 获取一次当前位置,用于快速初始化中心
Geolocator.getCurrentPosition().then((position) {
// 立即获取一次当前位置,用于快速初始化
try {
Position position = await Geolocator.getCurrentPosition();
_lastKnownPosition = position;
_syncLocationToMap(position, isInit: true);
});
_syncLocationToMap(position);
} catch (e) {
print("Error getting initial position: $e");
}
// 持续监听
// 持续监听位置变化
positionStream?.cancel(); // 先取消旧的监听
positionStream = Geolocator.getPositionStream(locationSettings: locationSettings)
.listen((Position position) {
_lastKnownPosition = position;
_syncLocationToMap(position, isInit: false);
});
_lastKnownPosition = position;
_syncLocationToMap(position);
});
}
// 将位置同步给 JS
void _syncLocationToMap(Position position, {required bool isInit}) {
if (webViewController == null) return;
// 将 Flutter 的定位数据同步给 JS
void _syncLocationToMap(Position position) {
if (webViewController == null || !isMapReady.value) return;
// 只有当 heading 有效且大于 0 时才传给 JS否则传 null让 JS 保持上一次的角度
String headingVal = (position.heading > 0) ? "${position.heading}" : "null";
// 如果是第一次定位,或者 WebView 刚加载完且从未设置过中心
if (isInit || !_hasInitializedMapCenter) {
webViewController!.evaluateJavascript(
source: "initLocation(${position.latitude}, ${position.longitude})"
);
_hasInitializedMapCenter = true;
} else {
// 后续只更新图标位置,不强行移动地图中心(防止用户拖动地图看别处时被拉回)
webViewController!.evaluateJavascript(
source: "updateMyLocation(${position.latitude}, ${position.longitude}, ${position.heading})"
);
}
webViewController!.evaluateJavascript(
source:
"updateMyLocation(${position.latitude}, ${position.longitude}, ${position.heading})",
);
}
// WebView 加载完成回调
void onWebViewLoadStop() {
// 页面加载完了,如果我们已经拿到了定位数据,立刻设置地图中心
if (_lastKnownPosition != null) {
_syncLocationToMap(_lastKnownPosition!, isInit: true);
}
// 如果业务需要,可以在这里加载默认的推荐路径
// loadRecommendedRoute();
}
// 模拟:获取你的后台推荐路径
void loadRecommendedRoute() {
// 示例数据
List<List<double>> routePoints = [
[116.397428, 39.90923],
[116.398000, 39.90950],
[116.400000, 39.91000],
];
String jsonPoints = jsonEncode(routePoints);
webViewController?.evaluateJavascript(source: "drawCustomRoute($jsonPoints)");
}
}
}