Flutter---GPS定位(2)
功能跳转主流地图APP实现步骤1.引入外部库map_launcher: ^4.5.0 #检测手机是否安装了主流地图 APP2.增加导航弹窗void showBottomSheetDialog(BuildContext context){ showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)) ), builder: (BuildContext context){ return Container( padding: EdgeInsets.symmetric( vertical: 20, //horizontal: 10 ), height: 250, child: Column( children: [ GestureDetector( onTap: () async { goGaodeMap(); }, child: Container( width: 325, height: 52, decoration: BoxDecoration( color: Color(0xFF4AC6AD).withOpacity(0.8), borderRadius: BorderRadius.circular(10) ), child: Center( child: Text(高德地图,style: TextStyle(color:Colors.white,fontSize: 18),), ), ), ), SizedBox(height: 5,), GestureDetector( onTap: (){ //跳转百度地图 goBaiduMap(); }, child: Container( width: 325, height: 52, decoration: BoxDecoration( color: Color(0xFF4AC6AD).withOpacity(0.8), borderRadius: BorderRadius.circular(10) ), child: Center( child: Text(百度地图,style: TextStyle(color:Colors.white,fontSize: 18),), ), ), ), SizedBox(height: 25,), Container( height: 1, width: double.infinity, color: Color(0xFFA8A8A8), ), SizedBox(height: 15,), GestureDetector( onTap: (){ Navigator.pop(context); }, child: Container( width: 325, height: 52, decoration: BoxDecoration( color: Color(0xFFA8A8A8), borderRadius: BorderRadius.circular(10) ), child: Center( child: Text(取消,style: TextStyle(color:Colors.white,fontSize: 18),), ), ), ), ], ), ); } ); }3.跳转地图的具体方法///跳转高德地图 Futurevoid goGaodeMap() async{ try { if (_currentPosition null) { Fluttertoast.showToast(msg: 请先获取当前位置); return; } // 检查高德地图是否安装 bool isAmapAvailable await map_launcher.MapLauncher.isMapAvailable(map_launcher.MapType.amap); if (isAmapAvailable) { print(高德地图已安装准备跳转); if (_currentAddress ! null) { await map_launcher.MapLauncher.showMarker( mapType: map_launcher.MapType.amap, coords: map_launcher.Coords( _currentPosition!.latitude, _currentPosition!.longitude ), title: , // 使用设备名称 description: 耳机位置, // 可选描述 ); print(跳转成功); } else { print(无法获取耳机位置); Fluttertoast.showToast(msg: 无法获取耳机位置); } } else { print(高德地图未安装); Fluttertoast.showToast(msg: 请先安装高德地图); } } catch (e) { print(跳转失败: $e); Fluttertoast.showToast(msg: 跳转失败); } Navigator.pop(context); } ///跳转百度地图 Futurevoid goBaiduMap() async{ try { if (_currentPosition null) { Fluttertoast.showToast(msg: 请先获取当前位置); return; } // 检查百度地图是否安装 bool isBaiduAvailable await map_launcher.MapLauncher.isMapAvailable(map_launcher.MapType.baidu); if (isBaiduAvailable) { print(高德地图已安装准备跳转); //耳机的位置 if (_currentAddress ! null) { await map_launcher.MapLauncher.showMarker( mapType: map_launcher.MapType.baidu, coords: map_launcher.Coords( _currentPosition!.latitude, _currentPosition!.longitude ), title: , // 使用设备名称 description: 耳机位置, // 可选描述 ); print(跳转成功); } else { print(无法获取耳机位置); Fluttertoast.showToast(msg: 无法获取耳机位置); } } else { print(高德地图未安装); Fluttertoast.showToast(msg: 请先安装百度地图); } } catch (e) { print(跳转失败: $e); Fluttertoast.showToast(msg: 跳转失败); } Navigator.pop(context); }代码实例import package:flutter/cupertino.dart; import package:flutter/material.dart; import package:fluttertoast/fluttertoast.dart; import package:geocoding/geocoding.dart; import package:geolocator/geolocator.dart; import package:map_launcher/map_launcher.dart as map_launcher; import location_service.dart; /// 设备查找页面 class DeviceFindPage extends StatefulWidget { const DeviceFindPage({super.key}); override StateStatefulWidget createState() _DeviceFindPageState(); } class _DeviceFindPageState extends StateDeviceFindPage { // 定位相关 final LocationService _locationService LocationService(); //定位服务实例 Position? _currentPosition; //当前位置 String _currentAddress ; //当前地址 bool _isLoadingLocation false; //加载状态 bool _hasLocationPermission false; //权限状态 // 文本资源 String findDevice 查找设备; String tapRing 点击唤醒; String tapRingTips 温馨提示唤醒设备后会发出声音请注意聆听; String addressTips 温馨提示app会标记设备断联前的最后位置您可以打开点击右边图标转进导航软件查看位置; override void initState() { super.initState(); // 设置定位回调 _setupLocationCallbacks(); // 页面加载时自动获取位置 WidgetsBinding.instance.addPostFrameCallback((_) { _getLocationAndAddress(); }); } override void dispose() { // 释放定位资源 _locationService.dispose(); super.dispose(); } //设置定位回调 void _setupLocationCallbacks() { _locationService.onLocationUpdated (Position position) { if (mounted) { setState(() { _currentPosition position; _hasLocationPermission true; }); // 位置更新时重新获取地址 _getAddressFromLatLng(position.latitude, position.longitude); } }; _locationService.onError (String error) { // Log.d(定位错误: $error); if (mounted) { setState(() { _currentAddress 定位失败: $error; _isLoadingLocation false; }); // 显示提示 ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(定位错误: $error), backgroundColor: Colors.red, ), ); } }; } //获取位置和地址 Futurevoid _getLocationAndAddress() async { if (_isLoadingLocation) return; setState(() { _isLoadingLocation true; _currentAddress 正在获取位置...; }); try { // 获取单次定位 Position? position await _locationService.getCurrentLocation(); if (position ! null mounted) { setState(() { _currentPosition position; _hasLocationPermission true; }); // 获取地址 await _getAddressFromLatLng(position.latitude, position.longitude); } } catch (e) { // Log.d(❌ 获取定位失败: $e); if (mounted) { setState(() { _currentAddress 获取位置失败请检查GPS设置; }); } } finally { if (mounted) { setState(() { _isLoadingLocation false; }); } } } //经纬度转地址 Futurevoid _getAddressFromLatLng(double latitude, double longitude) async { try { //地址解析 ListPlacemark placemarks await placemarkFromCoordinates( latitude, longitude, localeIdentifier: zh_CN, // 中文显示 ); if (placemarks.isNotEmpty mounted) { Placemark place placemarks[0]; // 构建详细地址 ListString addressParts []; // //国家 // if (place.country ! null place.country!.isNotEmpty) { // addressParts.add(place.country!); // } //省份 // if (place.administrativeArea ! null place.administrativeArea!.isNotEmpty) { // Log.d(⭐administrativeArea当前得到的值为${place.administrativeArea!}); // addressParts.add(place.administrativeArea!); // } // //城市 // if (place.locality ! null place.locality!.isNotEmpty) { // Log.d(⭐locality当前得到的值为${place.locality!}); // addressParts.add(place.locality!); // } // //区县 // if (place.subLocality ! null place.subLocality!.isNotEmpty) { // Log.d(⭐subLocality当前得到的值为${place.subLocality!}); // addressParts.add(place.subLocality!); // } //街道 if (place.street ! null place.street!.isNotEmpty) { // Log.d(⭐street当前得到的值为${place.street!}); addressParts.add(place.street!); } String fullAddress addressParts.join( ); // 如果地址为空使用经纬度 if (fullAddress.isEmpty) { fullAddress 纬度: $latitude, 经度: $longitude; } setState(() { _currentAddress fullAddress; _isLoadingLocation false; }); // Log.d( 当前地址: $fullAddress); // 如果需要上传到服务器在这里调用 // await YourHttpService.uploadLocation(latitude, longitude, fullAddress); } } catch (e) { // Log.d(❌ 获取地址失败: $e); if (mounted) { setState(() { _currentAddress 获取地址失败 (经纬度: $latitude, $longitude); _isLoadingLocation false; }); } } } override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xFFF5FCFF), appBar: AppBar( backgroundColor: Color(0xFFF5FCFF), leading: IconButton( onPressed: () { Navigator.pop(context); }, icon: Icon(Icons.arrow_back_ios), ), title: Text( findDevice, style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold), ), centerTitle: true, ), body: Container( width: double.infinity, height: double.infinity, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFFF5FCFF), Color(0xFFF2F4F5), ], ), ), child: Column( children: [ SizedBox(height: 10), // 查找容器 _buildFindContainer(), SizedBox(height: 40), // 详细地址显示定位信息 _buildAddress(), ], ), ), ); } // 查找容器 Widget _buildFindContainer() { return Container( width: double.infinity, height: 352, margin: EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( borderRadius: BorderRadius.circular(40), gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFFCFFFF5), Color(0xFFFFFFFF), ], ), boxShadow: [ BoxShadow( color: Color(0xFF000000).withOpacity(0.1), offset: Offset(3, 0), spreadRadius: 3, blurRadius: 5, ), ], ), child: Column( children: [ SizedBox(height: 20), // 产品图 Container( width: 150, height: 150, decoration: BoxDecoration( shape: BoxShape.circle, color: Color(0xFF777777).withOpacity(0.3), border: Border.all( color: Color(0xFF777777).withOpacity(0.2), width: 20, ), ), child: Center( child: Text(产品图), ), ), SizedBox(height: 50), // 响铃按钮 GestureDetector( onTap: () { // 点击时触发响铃 // Log.d(点击唤醒设备); }, child: Container( height: 52, width: 129, decoration: BoxDecoration( borderRadius: BorderRadius.circular(26), color: Color(0xFF4AC6AD), boxShadow: [ BoxShadow( color: Color(0xFF000000).withOpacity(0.1), offset: Offset(3, 0), spreadRadius: 3, blurRadius: 5, ), ], ), child: Center( child: Text( tapRing, style: TextStyle(color: Colors.white, fontSize: 18), ), ), ), ), Spacer(), // 温馨提示 Text( *$tapRingTips*, style: TextStyle(color: Color(0xFF3D3D3D), fontSize: 12), ), SizedBox(height: 20), ], ), ); } // 详细地址 Widget _buildAddress() { return Container( width: double.infinity, height: 196, margin: EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( borderRadius: BorderRadius.circular(31), color: Colors.white, boxShadow: [ BoxShadow( color: Color(0xFF000000).withOpacity(0.1), offset: Offset(3, 0), spreadRadius: 3, blurRadius: 5, ), ], ), child: Padding( padding: EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ //地址行 Row( children: [ //地址 Expanded(child: Text(_currentAddress,style: TextStyle(fontSize: 15,color: Color(0xFF3D3D3D)),)), //定位按钮 IconButton( onPressed: (){ showBottomSheetDialog(context); }, icon: Icon(Icons.navigation), ) ], ), //分割线 Container( height: 1, width: double.infinity, color: Colors.black.withOpacity(0.1), ), Spacer(), //温馨提示 Text( *$addressTips*, style: TextStyle(color: Color(0xFF3D3D3D), fontSize: 12), ), SizedBox(height: 5,), ], ), ), ); } //导航弹窗 void showBottomSheetDialog(BuildContext context){ showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)) ), builder: (BuildContext context){ return Container( padding: EdgeInsets.symmetric( vertical: 20, //horizontal: 10 ), height: 250, child: Column( children: [ GestureDetector( onTap: () async { goGaodeMap(); }, child: Container( width: 325, height: 52, decoration: BoxDecoration( color: Color(0xFF4AC6AD).withOpacity(0.8), borderRadius: BorderRadius.circular(10) ), child: Center( child: Text(高德地图,style: TextStyle(color:Colors.white,fontSize: 18),), ), ), ), SizedBox(height: 5,), GestureDetector( onTap: (){ //跳转百度地图 goBaiduMap(); }, child: Container( width: 325, height: 52, decoration: BoxDecoration( color: Color(0xFF4AC6AD).withOpacity(0.8), borderRadius: BorderRadius.circular(10) ), child: Center( child: Text(百度地图,style: TextStyle(color:Colors.white,fontSize: 18),), ), ), ), SizedBox(height: 25,), Container( height: 1, width: double.infinity, color: Color(0xFFA8A8A8), ), SizedBox(height: 15,), GestureDetector( onTap: (){ Navigator.pop(context); }, child: Container( width: 325, height: 52, decoration: BoxDecoration( color: Color(0xFFA8A8A8), borderRadius: BorderRadius.circular(10) ), child: Center( child: Text(取消,style: TextStyle(color:Colors.white,fontSize: 18),), ), ), ), ], ), ); } ); } ///跳转高德地图 Futurevoid goGaodeMap() async{ try { if (_currentPosition null) { Fluttertoast.showToast(msg: 请先获取当前位置); return; } // 检查高德地图是否安装 bool isAmapAvailable await map_launcher.MapLauncher.isMapAvailable(map_launcher.MapType.amap); if (isAmapAvailable) { print(高德地图已安装准备跳转); if (_currentAddress ! null) { await map_launcher.MapLauncher.showMarker( mapType: map_launcher.MapType.amap, coords: map_launcher.Coords( _currentPosition!.latitude, _currentPosition!.longitude ), title: , // 使用设备名称 description: 耳机位置, // 可选描述 ); print(跳转成功); } else { print(无法获取耳机位置); Fluttertoast.showToast(msg: 无法获取耳机位置); } } else { print(高德地图未安装); Fluttertoast.showToast(msg: 请先安装高德地图); } } catch (e) { print(跳转失败: $e); Fluttertoast.showToast(msg: 跳转失败); } Navigator.pop(context); } ///跳转百度地图 Futurevoid goBaiduMap() async{ try { if (_currentPosition null) { Fluttertoast.showToast(msg: 请先获取当前位置); return; } // 检查百度地图是否安装 bool isBaiduAvailable await map_launcher.MapLauncher.isMapAvailable(map_launcher.MapType.baidu); if (isBaiduAvailable) { print(高德地图已安装准备跳转); //耳机的位置 if (_currentAddress ! null) { await map_launcher.MapLauncher.showMarker( mapType: map_launcher.MapType.baidu, coords: map_launcher.Coords( _currentPosition!.latitude, _currentPosition!.longitude ), title: , // 使用设备名称 description: 耳机位置, // 可选描述 ); print(跳转成功); } else { print(无法获取耳机位置); Fluttertoast.showToast(msg: 无法获取耳机位置); } } else { print(高德地图未安装); Fluttertoast.showToast(msg: 请先安装百度地图); } } catch (e) { print(跳转失败: $e); Fluttertoast.showToast(msg: 跳转失败); } Navigator.pop(context); } }

相关新闻

没有开放集成与低代码,协同中台只是空谈

没有开放集成与低代码,协同中台只是空谈

当 CIO 查看企业 IM 后台时,常会发现一个尴尬的事实:每天超过 90% 的业务消息都在讨论订单、审批、客户变更,但这些对话永远停留在聊天窗口里,无法直接驱动 ERP 审批流,也不能自动同步到 CRM 客户时间线。另一边&#…

2026/7/24 17:38:24 阅读更多 →
一些感受与总结

一些感受与总结

prd对齐,那些情况要考虑,那些要做哪些不做trd评审,刚好为ai coding材料对齐,遇到问题多问,多和产品、研发和测试同学联系(终于知道以前为什么“明明是”这样却要拉一个会,明确哪些做哪些不做设计…

2026/7/24 17:38:24 阅读更多 →
Unity热重载实战:5分钟配置,告别编译等待,实时调试代码

Unity热重载实战:5分钟配置,告别编译等待,实时调试代码

1. 项目概述:为什么我们需要热重载?如果你是一名Unity开发者,无论是刚入门的新手,还是摸爬滚打多年的老手,下面这个场景你一定不陌生:为了测试一个简单的数值调整,比如把跳跃高度从5改成6&#…

2026/7/24 17:38:23 阅读更多 →

最新新闻

MSP430 SFR与SYS寄存器深度解析:中断、复位与系统配置实战指南

MSP430 SFR与SYS寄存器深度解析:中断、复位与系统配置实战指南

1. 项目概述与核心价值在嵌入式开发领域,尤其是与德州仪器(TI)的MSP430系列低功耗微控制器打交道时,我们经常会遇到一个核心概念:特殊功能寄存器。对于刚接触这类MCU的工程师来说,数据手册里那些密密麻麻的…

2026/7/24 17:46:27 阅读更多 →
终极虚拟显示器指南:如何用ParsecVDisplay轻松扩展Windows桌面空间

终极虚拟显示器指南:如何用ParsecVDisplay轻松扩展Windows桌面空间

终极虚拟显示器指南:如何用ParsecVDisplay轻松扩展Windows桌面空间 【免费下载链接】parsec-vdd ✨ Perfect virtual display for game streaming 项目地址: https://gitcode.com/gh_mirrors/pa/parsec-vdd 想要突破物理显示器的限制,让工作效率翻…

2026/7/24 17:46:27 阅读更多 →
MSP430系统控制模块:嵌入式低功耗设计的核心枢纽

MSP430系统控制模块:嵌入式低功耗设计的核心枢纽

1. MSP430系统控制模块:嵌入式低功耗设计的核心枢纽在嵌入式开发领域,尤其是对功耗极其敏感的电池供电设备中,德州仪器(TI)的MSP430系列微控制器(MCU)一直是工程师们的“心头好”。它那令人惊叹…

2026/7/24 17:46:27 阅读更多 →
AI在癌症诊疗中的Web应用开发实践

AI在癌症诊疗中的Web应用开发实践

1. 项目背景与核心价值 癌症诊疗领域正在经历一场由AI技术驱动的革命性变革。作为一名长期关注医疗科技交叉领域的技术从业者,我亲眼见证了AI算法从辅助诊断工具逐步发展为临床决策关键支撑的全过程。这个初版网页项目正是要搭建一个展示窗口,让医疗从业…

2026/7/24 17:46:27 阅读更多 →
声控游戏下载安装全攻略:从原理到实战解决闪退问题

声控游戏下载安装全攻略:从原理到实战解决闪退问题

最近不少朋友在问:这个"啊啊啊声控游戏"到底怎么下载?安装过程复杂吗?为什么我下载后总是闪退?如果你也在寻找这款声控游戏的完整安装指南,那么这篇文章就是为你准备的。 作为一个体验过多款声控游戏的开发…

2026/7/24 17:46:26 阅读更多 →
基于SpringBoot3+Vue3的家政服务系统(源码)

基于SpringBoot3+Vue3的家政服务系统(源码)

目录 一、项目背景 二、技术介绍 三、功能介绍 四、代码设计 五、系统实现 一、项目背景 随着我国居民生活水平持续提升与人口老龄化进程加快,家政服务已从昔日的“小众需求”发展为覆盖保洁、养老、育婴、收纳等多场景的万亿级刚需市场。据行业数据显示&…

2026/7/24 17:45:26 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值,并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/24 3:59:20 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻