flutter 集成高德地图,获取定位以及展示地图高德地图

flutter 集成高德地图,获取定位以及展示地图高德地图

打包项目,获取证书文件

  1. 点击android studio界面左上方File>open,切换到项目下的android文件夹。


2. 点击 android studio 界面左上方 Build>Generate Signed Bundle / APK , 选择 APK 然后 next 。


下一步点击Create New创建证书


填写证书信息,创建完成后点击 next,进入选择打包类型界面

Key store path: 是你要将 key 保存在哪里,可以先找个地方放,后面可以 copy 到其它地方。 Password:为您的密钥库创建并确认一个安全的密码。

Validity (years) :以年为单位设置密钥的有效时长。密钥的有效期应至少为 25 年。

Certificate:为证书输入一些关于您本人的信息。此信息不会显示在应用中,但会作为 APK 的一部分包含在您的证书中。只有第一项是必须填的,其它的空着就行。当然了,如果写全了更好。

这里选择 relesse 打包,点击 Create 完成打包后就可以在指定的目录看到证书

  1. 使用 keytool(jdk自带工具)获取 SHA1

    控制台中定位到之前生成的证书文件夹中 ,输入命令 keytool -list -v -keystore 证书文件名 。提示输入密钥库口令,发布模式的密码是为 apk 的 keystore 设置的密码 。这时就能在控制台中看到该证书的 SHA1

高德地图官方 appkey 申请

  1. 进入高德控制台,创建新应用

    高德控制台没有账号的话需要注册,进入应用管理>我的应用,点击右上角创建新应用,在弹出的界面输入应用名和类型。

  2. 新建完的应用就会出现在我的应用中,点击添加key,按照说明添加信息。根据自己的需要添加需要绑定的服务。

使用amap_flutter_location_plus插件完成定位

  1. 安装amap_flutter_location_plus插件以及permission_handler权限申请插件

    yaml 复制代码
     permission_handler: ^12.0.1
     amap_flutter_location_plus: ^3.1.2
     x_amap_base: ^1.0.3
  2. 修改修改 android/app/src/main/AndroidManifest.xml

    添加权限

    xml 复制代码
    <!--访问网络-->
       <uses-permission android:name="android.permission.INTERNET" />
       <!--粗略定位-->
       <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
       <!--精确定位-->
       <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
       <!--申请调用 A-GPS 模块-->
       <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
       <!--用于获取运营商信息,用于支持提供运营商信息相关的接口-->
       <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
       <!--用于访问 wifi 网络信息,wifi 信息会用于进行网络定位-->
       <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
       <!--用于获取 wifi 的获取权限,wifi 信息会用来进行网络定位-->
       <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
       <!--用于读取手机当前的状态-->
       <uses-permission android:name="android.permission.READ_PHONE_STATE" />
       <!--用于写入缓存数据到扩展存储卡-->
       <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    配置定位Service

    xml 复制代码
       <!-- 配置定位 Service -->
        <service android:name="com.amap.api.location.APSService"/>
  3. 在 /app/build.gradle .kts文件中加入签名文件

    android闭包中添加

    ini 复制代码
    signingConfigs {  
      create("release") {  
      storeFile = file("amap.jks")  
      storePassword = "123456"  
      keyAlias = "key0"  
      keyPassword = "123456"  
      }  
      create("customDebug") { // 修改为不同名称  
      storeFile = file("amap.jks")  
      storePassword = "123456"  
      keyAlias = "key0"  
      keyPassword = "123456"  
      }  
     }  
     buildTypes {  
      getByName("release") {  
      signingConfig = signingConfigs.getByName("release")  
      }  
      getByName("debug") {  
      signingConfig = signingConfigs.getByName("customDebug") // 对应修改  
      }
     }
  4. 定位示例

    注意:需要将示例中放入 appkey 的地方放入自己生成的 key

    1. const_config.dart 相关key配置文件

      php 复制代码
      import 'package:x_amap_base/x_amap_base.dart';
      
      class ConstConfig {
      /// 安卓key
      static const androidKey = '6d568aed19b1e76db1be502c23e88518';
      
      /// 苹果key
      static const iosKey = 'ded8cfcf09e8b20d0320f8b67e9a80a5';
      
      /// web服务
      static const webKey = 'c9ec1228be59c713bc1445c34d6b8489';
      
      static const AMapApiKey amapApiKeys = AMapApiKey(
        //androidKey: '900f72eeee0f21e435cebb0ef155582a',
        androidKey: androidKey,
        //iosKey: '4dfdec97b7bf0b8c13e94777103015a9'
        iosKey: iosKey,
      );
      static const AMapPrivacyStatement amapPrivacyStatement = AMapPrivacyStatement(
        hasContains: true,
        hasShow: true,
        hasAgree: true,
      );
      }
    2. location.dart定位代码

      dart 复制代码
      import 'dart:async';
      import 'dart:io';
      import 'package:amap_flutter_location_plus/amap_flutter_location_plus.dart';
      import 'package:amap_flutter_location_plus/amap_location_option.dart';
      import 'package:flutter/material.dart';
      import 'package:permission_handler/permission_handler.dart';
      import '../config/const_config.dart';
      
      class LocationPage extends StatefulWidget {
      const LocationPage({Key? key}) : super(key: key);
      
      @override
      State<LocationPage> createState() => _LocationPageState();
      }
      
      class _LocationPageState extends State<LocationPage> {
      String _latitude = ""; //纬度
      String _longitude = ""; //经度
      String country = ""; // 国家
      String province = ""; // 省份
      String city = ""; // 市
      String district = ""; // 区
      String street = ""; // 街道
      String adCode = ""; // 邮编
      String address = ""; // 详细地址
      String cityCode = ""; //区号
      
      // 实例化
      final AMapFlutterLocation _locationPlugin = AMapFlutterLocation();
      // 监听定位
      late StreamSubscription<Map<String, Object>> _locationListener;
      
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
      
        /// 动态申请定位权限
        requestPermission();
      
        /// 设置Android和iOS的apikey,
        AMapFlutterLocation.setApiKey(ConstConfig.androidKey, ConstConfig.iosKey);
      
        ///设置是否已经取得用户同意,如果未取得用户同意,高德定位SDK将不会工作,这里传true
        AMapFlutterLocation.updatePrivacyAgree(true);
      
        /// 设置是否已经包含高德隐私政策并弹窗展示显示用户查看,如果未包含或者没有弹窗展示,高德定位SDK将不会工作,这里传true
        AMapFlutterLocation.updatePrivacyShow(true, true);
      
        ///iOS 获取native精度类型
        if (Platform.isIOS) {
          requestAccuracyAuthorization();
        }
        ///注册定位结果监听
        _locationListener = _locationPlugin.onLocationChanged().listen((
          Map<String, Object> result,
        ) {
          print(result);
      
          setState(() {
            _latitude = result["latitude"].toString();
            _longitude = result["longitude"].toString();
            country = result['country'].toString();
            province = result['province'].toString();
            city = result['city'].toString();
            district = result['district'].toString();
            street = result['street'].toString();
            adCode = result['adCode'].toString();
            address = result['address'].toString();
            cityCode = result['cityCode'].toString();
          });
        });
      }
      
      @override
      void dispose() {
        super.dispose();
      
        ///移除定位监听
        _locationListener.cancel();
      
        ///销毁定位
        _locationPlugin.destroy();
        }
      
      /// 动态申请定位权限
      void requestPermission() async {
        // 申请权限
        bool hasLocationPermission = await requestLocationPermission();
        if (hasLocationPermission) {
          print("定位权限申请通过");
        } else {
          print("定位权限申请不通过");
        }
      }
      
      /// 申请定位权限
      /// 授予定位权限返回true, 否则返回false
      Future<bool> requestLocationPermission() async {
        //获取当前的权限
        var status = await Permission.location.status;
        if (status == PermissionStatus.granted) {
          //已经授权
          return true;
        } else {
          //未授权则发起一次申请
          status = await Permission.location.request();
          if (status == PermissionStatus.granted) {
            return true;
          } else {
            return false;
          }
        }
      }
      
      ///获取iOS native的accuracyAuthorization类型
      void requestAccuracyAuthorization() async {
        //iOS 14中系统的定位类型信息
        AMapAccuracyAuthorization currentAccuracyAuthorization =
            await _locationPlugin.getSystemAccuracyAuthorization();
        if (currentAccuracyAuthorization ==
            AMapAccuracyAuthorization.AMapAccuracyAuthorizationFullAccuracy) {
          print("精确定位类型");
        } else if (currentAccuracyAuthorization ==
            AMapAccuracyAuthorization.AMapAccuracyAuthorizationReducedAccuracy) {
          print("模糊定位类型");
        } else {
          print("未知定位类型");
        }
      }
      
      ///设置定位参数
      void _setLocationOption() {
        if (null != _locationPlugin) {
          AMapLocationOption locationOption = AMapLocationOption();
      
          ///是否单次定位
          locationOption.onceLocation = false;
      
          ///是否需要返回逆地理信息
          locationOption.needAddress = true;
      
          ///逆地理信息的语言类型
          locationOption.geoLanguage = GeoLanguage.DEFAULT;
      
          locationOption.desiredLocationAccuracyAuthorizationMode =
              AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;
      
          locationOption.fullAccuracyPurposeKey = "AMapLocationScene";
      
          ///设置Android端连续定位的定位间隔
          locationOption.locationInterval = 2000;
      
          ///设置Android端的定位模式<br>
          ///可选值:<br>
          ///<li>[AMapLocationMode.Battery_Saving]</li>
          ///<li>[AMapLocationMode.Device_Sensors]</li>
          ///<li>[AMapLocationMode.Hight_Accuracy]</li>
          locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
      
          ///设置iOS端的定位最小更新距离<br>
          locationOption.distanceFilter = -1;
      
          ///设置iOS端期望的定位精度
          /// 可选值:<br>
          /// <li>[DesiredAccuracy.Best] 最高精度</li>
          /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
          /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
          /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
          /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
          locationOption.desiredAccuracy = DesiredAccuracy.Best;
      
          ///设置iOS端是否允许系统暂停定位
          locationOption.pausesLocationUpdatesAutomatically = false;
      
          ///将定位参数设置给定位插件
          _locationPlugin.setLocationOption(locationOption);
        }
      }
      
      ///开始定位
      void _startLocation() {
        if (null != _locationPlugin) {
          ///开始定位之前设置定位参数
          _setLocationOption();
          _locationPlugin.startLocation();
        }
      }
      
      ///停止定位
      void _stopLocation() {
        if (null != _locationPlugin) {
          _locationPlugin.stopLocation();
        }
      }
      
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('定位')),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text("经度:$_longitude"),
                Text("纬度:$_latitude"),
                Text('国家:$country'),
                Text('省份:$province'),
                Text('城市:$city'),
                Text('区:$district'),
                Text('城市编码:$cityCode'),
                Text('街道:$street'),
                Text('邮编:$adCode'),
                Text('详细地址:$address'),
                SizedBox(height: 20),
                ElevatedButton(
                  child: const Text('开始定位'),
                  onPressed: () {
                    _startLocation();
                  },
                ),
                ElevatedButton(
                  child: const Text('停止定位'),
                  onPressed: () {
                    _stopLocation();
                  },
                ),
              ],
            ),
          ),
        );
      }
      }

使用amap_map展示高德地图

  1. 安装amap_map

    注意权限配置和amap_flutter_location_plus是一样的

    dart 复制代码
    amap_map: ^1.0.15
  2. 地图展示

    dart 复制代码
    import 'package:amap_map/amap_map.dart';
    import 'package:flutter/material.dart';
    import '../config/const_config.dart';
    
    class ShowMapPage extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => _ShowMapPageState();
    }
    
    class _ShowMapPageState extends State<ShowMapPage> {
      late AMapController _mapController;
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
      }
    
      final List<Widget> _approvalNumberWidget = <Widget>[];
      @override
      Widget build(BuildContext context) {
        // 需要添加否则高德地图不会工作
        AMapInitializer.init(context, apiKey: ConstConfig.amapApiKeys);
        AMapInitializer.updatePrivacyAgree(ConstConfig.amapPrivacyStatement);
        final AMapWidget map = AMapWidget(
          onMapCreated: (controller) {
            setState(() {
              _mapController = controller;
              getApprovalNumber();
            });
          },
        );
    
        return Scaffold(
          body: ConstrainedBox(
            constraints: BoxConstraints.expand(),
            child: Stack(
              alignment: Alignment.center,
              children: [
                SizedBox(
                  height: MediaQuery.of(context).size.height,
                  width: MediaQuery.of(context).size.width,
                  child: map,
                ),
                Positioned(
                  right: 10,
                  bottom: 15,
                  child: Container(
                    alignment: Alignment.centerLeft,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: _approvalNumberWidget,
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    
      //获取审图号
      void getApprovalNumber() async {
        //普通地图审图号
        String mapContentApprovalNumber = (await _mapController
            .getMapContentApprovalNumber());
        //卫星地图审图号
        String satelliteImageApprovalNumber = (await _mapController
            .getSatelliteImageApprovalNumber());
    
        setState(() {
          _approvalNumberWidget.add(
            Text(
              mapContentApprovalNumber,
              style: TextStyle(color: Colors.red, fontSize: 12),
            ),
          );
          _approvalNumberWidget.add(
            Text(
              satelliteImageApprovalNumber,
              style: TextStyle(color: Colors.red, fontSize: 12),
            ),
          );
        });
        print('地图审图号(普通地图): $mapContentApprovalNumber');
        print('地图审图号(卫星地图): $satelliteImageApprovalNumber');
      }
    }
  1. 点击地图显示相应的周边信息

    显示周边信息需要用到高德地图的web服务,将web服务的key替换

    dart 复制代码
    import 'dart:async';
    import 'dart:io';
    import 'package:amap_flutter_location_plus/amap_flutter_location_plus.dart';
    import 'package:amap_flutter_location_plus/amap_location_option.dart';
    import 'package:amap_map/amap_map.dart';
    import 'package:dio/dio.dart';
    import 'package:flutter/material.dart';
    import 'package:logger/logger.dart';
    import 'package:permission_handler/permission_handler.dart';
    import 'package:x_amap_base/x_amap_base.dart';
    import '../config/const_config.dart';
    import '../model/address_parsing.dart';
    import '../util/lat_lng_tween.dart';
    
    class ShowMapPositionData extends StatefulWidget {
      const ShowMapPositionData({Key? key}) : super(key: key);
    
      @override
      State<ShowMapPositionData> createState() => _ShowMapPositionDataState();
    }
    
    class _ShowMapPositionDataState extends State<ShowMapPositionData>
        with TickerProviderStateMixin {
      late double _latitude; //纬度
      late double _longitude; //经度
    
      // 实例化
      final AMapFlutterLocation _locationPlugin = AMapFlutterLocation();
      // 监听定位
      late StreamSubscription<Map<String, Object>> _locationListener;
      AMapController? _controller;
      LatLng? _clickLocation;
      bool _isLocationAvailable = false;
      Marker? marker;
      var logger = Logger();
      // 动画相关变量
      AnimationController? _animationController;
      Animation<LatLng>? _positionAnimation;
      bool _isFirstLocation = true;
    
      /// 周边数据
      AddressParsing? poisData;
    
      // 带动画移动marker
      void moveMarkerWithAnimation(LatLng newPosition) {
        if (marker == null) return;
    
        // 释放之前的动画控制器
        _animationController?.dispose();
    
        // 创建新的动画控制器
        _animationController = AnimationController(
          duration: const Duration(milliseconds: 2000),
          vsync: this,
        );
    
        // 创建位置插值动画 使用自定义的LatLngTween
        _positionAnimation = LatLngTween(begin: marker!.position, end: newPosition)
            .animate(
              CurvedAnimation(
                parent: _animationController!,
                curve: Curves.easeInOut,
              ),
            );
    
        // 监听动画更新
        _animationController!.addListener(() {
          setState(() {
            marker = marker?.copyWith(positionParam: _positionAnimation!.value);
          });
        });
    
        // 监听动画状态
    
        // 启动动画
        _animationController!.forward();
      }
    
      void getPoisData() async {
        /// 获取周边数据
    
        if (_clickLocation != null) {
          var response = await Dio().get(
            'https://restapi.amap.com/v3/place/around?key=${ConstConfig.webKey}&location=${_clickLocation!.latitude},'
            '${_clickLocation!.longitude}&keywords=&types=&radius=1000&offset=20&page=1&extensions=base',
          );
    
          // 解析返回的数据为 AddressParsing 列表
          AddressParsing? parsedData;
          if (response.data != null) {
            parsedData = AddressParsing.fromJson(response.data);
          }
    
          setState(() {
            poisData = parsedData;
          });
        }
      }
    
      @override
      void initState() {
        super.initState();
        _initializeLocationService();
      }
    
      /// 初始化定位服务
      void _initializeLocationService() {
        _setupPrivacySettings();
        _setupPlatformSpecificFeatures();
        _setupLocationListener();
        _setLocationOption();
        _locationPlugin.startLocation();
      }
    
      /// 设置隐私相关配置
      void _setupPrivacySettings() {
        AMapFlutterLocation.updatePrivacyAgree(true);
        AMapFlutterLocation.updatePrivacyShow(true, true);
      }
    
      /// 设置平台特定功能
      void _setupPlatformSpecificFeatures() {
        if (Platform.isIOS) {
          requestAccuracyAuthorization();
        }
      }
    
      /// 设置定位监听器
      void _setupLocationListener() {
        _locationListener = _locationPlugin.onLocationChanged().listen(
          _handleLocationResult,
        );
      }
    
      /// 处理定位结果
      void _handleLocationResult(Map<String, Object> result) {
        print(result);
    
        if (mounted) {
          setState(() {
            _latitude = (result['latitude'] as num).toDouble();
            _longitude = (result['longitude'] as num).toDouble();
            if (_isFirstLocation) {
              _clickLocation = LatLng(_latitude, _longitude);
              _isFirstLocation = false;
            }
            _isLocationAvailable = true;
            // 在获取定位后创建marker
            addMarker();
            // 在获取定位后获取周边数据
            getPoisData();
          });
        }
      }
    
      // 设置定位参数
      void _setLocationOption() {
        AMapLocationOption locationOption = AMapLocationOption();
    
        ///是否单次定位
        locationOption.onceLocation = false;
    
        ///是否需要返回逆地理信息
        locationOption.needAddress = true;
    
        ///逆地理信息的语言类型
        locationOption.geoLanguage = GeoLanguage.DEFAULT;
    
        locationOption.desiredLocationAccuracyAuthorizationMode =
            AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;
    
        locationOption.fullAccuracyPurposeKey = "AMapLocationScene";
    
        ///设置Android端连续定位的定位间隔
        locationOption.locationInterval = 2000;
    
        ///设置Android端的定位模式<br>
        ///可选值:<br>
        ///<li>[AMapLocationMode.Battery_Saving]</li>
        ///<li>[AMapLocationMode.Device_Sensors]</li>
        ///<li>[AMapLocationMode.Hight_Accuracy]</li>
        locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
    
        ///设置iOS端的定位最小更新距离<br>
        locationOption.distanceFilter = -1;
    
        ///设置iOS端期望的定位精度
        /// 可选值:<br>
        /// <li>[DesiredAccuracy.Best] 最高精度</li>
        /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
        /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
        /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
        /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
        locationOption.desiredAccuracy = DesiredAccuracy.Best;
    
        ///设置iOS端是否允许系统暂停定位
        locationOption.pausesLocationUpdatesAutomatically = false;
    
        ///将定位参数设置给定位插件
        _locationPlugin.setLocationOption(locationOption);
      }
    
      @override
      void dispose() {
        super.dispose();
    
        ///移除定位监听
        _locationListener.cancel();
    
        ///销毁定位
        _locationPlugin.destroy();
    
        // 释放动画控制器
        _animationController?.dispose();
      }
    
      /// 动态申请定位权限
      void requestPermission() async {
        // 申请权限
        bool hasLocationPermission = await requestLocationPermission();
        if (hasLocationPermission) {
          print("定位权限申请通过");
        } else {
          print("定位权限申请不通过");
        }
      }
    
      /// 申请定位权限
      /// 授予定位权限返回true, 否则返回false
      Future<bool> requestLocationPermission() async {
        //获取当前的权限
        var status = await Permission.location.status;
        if (status == PermissionStatus.granted) {
          //已经授权
          return true;
        } else {
          //未授权则发起一次申请
          status = await Permission.location.request();
          if (status == PermissionStatus.granted) {
            return true;
          } else {
            return false;
          }
        }
      }
    
      ///获取iOS native的accuracyAuthorization类型
      void requestAccuracyAuthorization() async {
        //iOS 14中系统的定位类型信息
        AMapAccuracyAuthorization currentAccuracyAuthorization =
            await _locationPlugin.getSystemAccuracyAuthorization();
        if (currentAccuracyAuthorization ==
            AMapAccuracyAuthorization.AMapAccuracyAuthorizationFullAccuracy) {
          print("精确定位类型");
        } else if (currentAccuracyAuthorization ==
            AMapAccuracyAuthorization.AMapAccuracyAuthorizationReducedAccuracy) {
          print("模糊定位类型");
        } else {
          print("未知定位类型");
        }
      }
    
      // 添加marker
      void addMarker() {
        if (marker == null && _clickLocation != null) {
          setState(() {
            marker = Marker(
              position: _clickLocation!,
              anchor: const Offset(0.5, 0.5),
              draggable: true,
            );
          });
        }
      }
    
      @override
      Widget build(BuildContext context) {
        // 需要添加否则高德地图不会工作
        AMapInitializer.init(context, apiKey: ConstConfig.amapApiKeys);
        AMapInitializer.updatePrivacyAgree(ConstConfig.amapPrivacyStatement);
        return Scaffold(
          appBar: AppBar(title: const Text('定位')),
          body: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              SizedBox(
                width: MediaQuery.of(context).size.width,
                height: MediaQuery.of(context).size.height * 0.6,
                child: _isLocationAvailable
                    ? AMapWidget(
                        initialCameraPosition: CameraPosition(
                          target: LatLng(_latitude, _longitude),
                        ),
                        markers: marker != null ? <Marker>{marker!} : <Marker>{},
                        onTap: (latLng) {
                          setState(() {
                            _clickLocation = latLng;
                          });
                          logger.i(_clickLocation?.toJson());
    
                          if (marker != null) {
                            // 如果已有标记点,则带动画移动
                            moveMarkerWithAnimation(latLng);
                          } else {
                            // 如果没有标记点,则创建新标记点
                            addMarker();
                          }
                        },
                      )
                    : SizedBox.shrink(),
              ),
              Expanded(
                child: SingleChildScrollView(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: poisData != null
                        ? poisData!.pois
                              .map(
                                (poi) => Padding(
                                  padding: const EdgeInsets.all(8.0),
                                  child: Text(
                                    '${poi.name} - ${poi.address} (${poi.distance}米)',
                                    style: const TextStyle(fontSize: 16),
                                  ),
                                ),
                              )
                              .toList()
                        : [const Text('暂无数据')],
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }

    LatLngTween动画工具类

    dart 复制代码
    class LatLngTween extends Tween<LatLng> {
      LatLngTween({required LatLng begin, required LatLng end})
        : super(begin: begin, end: end);
    
      @override
      LatLng lerp(double t) {
        return LatLng(
          begin!.latitude + (end!.latitude - begin!.latitude) * t,
          begin!.longitude + (end!.longitude - begin!.longitude) * t,
        );
      }
    }

amap_map插件相关参数

参数 类型 描述
initialCameraPosition CameraPosition 初始化地图的中心点位置
mapType MapType 地图类型(如普通地图、卫星地图等)
customStyleOptions CustomStyleOptions? 自定义地图样式选项(可为空)
myLocationStyleOptions MyLocationStyleOptions? 定位小蓝点样式选项(可为空)
minMaxZoomPreference MinMaxZoomPreference? 地图的最小和最大缩放级别(可为空)
limitBounds LatLngBounds? 设置地图显示的区域边界(可为空)
trafficEnabled bool 是否启用交通图层
touchPoiEnabled bool 是否允许点击地图上的POI(兴趣点)
buildingsEnabled bool 是否显示3D建筑物
labelsEnabled bool 是否显示地图上的文字标签
compassEnabled bool 是否显示指南针
scaleEnabled bool 是否显示比例尺
zoomGesturesEnabled bool 是否启用缩放手势
scrollGesturesEnabled bool 是否启用滑动手势
rotateGesturesEnabled bool 是否启用旋转手势
tiltGesturesEnabled bool 是否启用倾斜手势
logoPosition LogoPosition? 地图logo的位置(高德地图Android特有)
logoBottomMargin int? logo底部的间距(高德地图Android特有)
logoLeftMargin int? logo左侧的间距(高德地图Android特有)
markers Set<Marker> 地图上显示的标记点集合
polylines Set<Polyline> 地图上显示的折线集合
polygons Set<Polygon> 地图上显示的多边形集合
onMapCreated MapCreatedCallback? 地图创建成功后的回调,只有在此回调之后才能操作地图
onCameraMove ArgumentCallback<CameraPosition>? 相机视角持续移动时的回调
onCameraMoveEnd ArgumentCallback<CameraPosition>? 相机视角停止移动时的回调
onTap ArgumentCallback<LatLng>? 地图单击事件的回调
onLongPress ArgumentCallback<LatLng>? 地图长按事件的回调
onPoiTouched ArgumentCallback<AMapPoi>? POI点击回调,需开启touchPoiEnabled才能触发
onLocationChanged ArgumentCallback<AMapLocation>? 位置变化的回调
gestureRecognizers Set<Factory<OneSequenceGestureRecognizer>> 要应用到地图上的手势集合
mapLanguage MapLanguage? 地图的语言设置(目前只支持简体中文和英文)
infoWindowAdapter InfoWindowAdapter? Marker信息窗口适配器

关于高德地图插件的使用情况就介绍到这里有兴趣的可以去查看官方示例,我也是在官方示例基础上进行的修改。

相关推荐
落一落,掉一掉2 小时前
第十二周 waf绕过和前端加密绕过
前端
Asort2 小时前
JavaScript设计模式(十六)——迭代器模式:优雅遍历数据的艺术
前端·javascript·设计模式
Coffeeee2 小时前
Labubu很难买?那是因为还没有用Compose来画一个
前端·kotlin·android jetpack
我是日安2 小时前
从零到一打造 Vue3 响应式系统 Day 28 - shallowRef、shallowReactive
前端·javascript·vue.js
开源之眼2 小时前
深入理解 JavaScript 报错:TypeError: undefined is not a function
前端·javascript
LRH2 小时前
时间切片 + 双工作循环 + 优先级模型:React 的并发任务管理策略
前端·react.js
用户3421674905522 小时前
Java高手速成--吃透源码+手写组件+定制开发教程
前端·深度学习
却尘2 小时前
当你敲下 `pnpm run dev`,这台机器到底在背后干了什么?
前端·javascript·面试
歪歪1002 小时前
React Native开发有哪些优势和劣势?
服务器·前端·javascript·react native·react.js·前端框架