Flutter开发 -flutter百度地图接入指南,外加定位,反地理编码,这些功能组成一个类似饿了么的配送员配送界面,这些功能你心动么?

本文介绍了在Flutter中如何接入百度地图,实现定位、反地理编码和配送员界面功能。通过引入地图库、设置初始化,创建地图,并利用特定库实现定位和反地理编码。同时,展示了抽屉功能、滑动按钮、插旗更新位置等组件的实现,提供了完整页面代码供参考。

今天这篇博客说的是地图和定位的问题,不一样的是,这是在flutter中处理地图,定位,反地理编码。

先看下做出来的效果如何:
在这里插入图片描述

目前用到的都是模拟数据,真实场景大家自己接入数据即可。

这里的功能分为几部分:

1.百度地图;
2.定位功能;(百度地图提供了定位功能,需要单独引入,但是这里选择使用其他的基于LBS的定位)
3.反地理编码;
4.抽屉功能;(就是这个可以拖拽的列表,可展开,可折叠)
5.滑动按钮;
6.插旗和更新位置信息;
7.总结和页面完整代码。

然后我们来一步步说明怎么来使用这些功能:

1.百度地图


百度地图flutter插件接入地址:http://lbsyun.baidu.com/index.php?title=flutter/loc

至于接入的部分,大家参照文档来接入,不再赘述。
引入地图库:

  flutter_baidu_mapapi_map: ^2.0.0

地图在接入后需要初始化:

    // 百度地图sdk初始化鉴权
    if (Platform.isIOS) {
      BMFMapSDK.setApiKeyAndCoordType(
          'xxxxxxxxxxxxxxxxxxxx', BMF_COORD_TYPE.COMMON);
    } else if (Platform.isAndroid) {
      // Android 目前不支持接口设置Apikey,
      // 请在主工程的Manifest文件里设置,详细配置方法请参考官网(https://lbsyun.baidu.com/)demo
      BMFMapSDK.setCoordType(BMF_COORD_TYPE.COMMON);
    }

这样就完成了地图的接入准备工作。

接着我们来创建地图:

  @override
  Container generateMap() {
    return Container(
      height: screenSize.height,
      width: screenSize.width,
      child: BMFMapWidget(
          onBMFMapCreated: (controller) {
            onBMFMapCreated(controller);
          },
          mapOptions: initMapOptions(latitude: dposition?.latitude ?? (widget.latitude ?? 39.928617), longitude: dposition?.longitude ?? (widget.longitude ?? 116.40329))
      ),
    );
  }


  /// 设置地图参数
  BMFMapOptions initMapOptions({double latitude, double longitude}) {
    BMFCoordinate coordinate = BMFCoordinate(latitude ??widget.latitude, longitude ?? widget.longitude);
    BMFMapOptions mapOptions = BMFMapOptions(
        center: coordinate,
        zoomLevel: 12,
        mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 0));
    return mapOptions;
  }

这里,iOS要注意两个点:

1.要设置Bundle display name,否则iOS地图启动会失败;

2.新项目要添加SWIFT_VERSION,否则会报大量的swift错误,项目无法运行;
在这里插入图片描述

2.定位功能


百度地图提供了定位的功能,和百度地图也是配套使用的,
引入定位插件:

flutter_bmflocation: ^1.0.2 

这里官网有个误解:
在这里插入图片描述
看这张图,按照图上的指引去配置,根本跑不起来,这也是为什么博主选择通过其他方式来定位的原因,后面提了工单,说是不需要做任何的配置,pod install之后会自动完成所有的配置,大家可以自己尝试下,相信官方不至于乱说,这里切记一定不要手动配置。

那这里说说博主是怎么不通过百度定位来做定位功能的:
首先引入定位的库:

  geolocator: 6.2.1

这里的版本建议大家写死,因为在之前的版本定位和反地理编码是在同一个库里面的,后面拆开了,稍后会说反地理编码的库。

///定位功能,会获取接触的经纬度信息
Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best);

3.反地理编码


定位里面说了,反地理编码是在定位的库里面拆分出来的,这里引入的库名为:

  geocoding: 1.0.1

反地理编码需要在真机上才能执行,注意下,代码如下:

  Future<String> _getAddressFromLatLng() async {
    try {
      List<Placemark> p = await placemarkFromCoordinates(
          dposition?.latitude ?? 39.928617, dposition?.longitude ?? 116.40329);
      Placemark place = p[0];
      print("${place?.locality ?? ''}${place?.subLocality ?? ''}${place?.street ?? ''}");
      String locationStr = "${place?.locality ?? ''}${place?.subLocality ?? ''}${place?.street ?? ''}";
      _marker.updateSubTitle(locationStr);
      return locationStr;
    } catch (e) {
      print(e);
    }
  }

这个方法会返回地理位置的名字,这个方法很简单。

4.抽屉功能


这个抽屉的功能稍微有点复杂,推荐使用一个库:

  drag_container: 1.0.2

使用介绍:

  ///构建底部对齐的抽屉效果视图
  Widget buildDragWidget(){
    ///层叠布局中的底部对齐
    return Align(
      alignment: Alignment.bottomCenter,
      child: DragContainer(
        ///抽屉关闭时的高度 默认0.4
        initChildRate: 0.2,
        ///抽屉打开时的高度 默认0.4
        maxChildRate: 0.9,
        ///是否显示默认的标题
        isShowHeader: true,
        ///背景颜色
        backGroundColor: Colors.transparent,
        ///背景圆角大小
        cornerRadius: 12,
        ///自动上滑动或者是下滑的分界值
        maxOffsetDistance:1.5,
        ///抽屉控制器
        controller: dragController,
        ///滑动控制器
        scrollController: scrollController,
        ///自动滑动的时间
        duration: Duration(milliseconds: 800),
        ///抽屉的子Widget
        dragWidget: buildListView(),
        ///抽屉标题点击事件回调
        dragCallBack: (isOpen){
          _show = isOpen;
          setState(() {

          });
        },
        ///列表到顶向下滑动可关闭
        useAtEdge: true,
      ),
    );
  }

buildListView就写自己的列表Ui就可以了,里面属性很多,根据自己的需要来设置。

5.滑动按钮


说起来,flutter的轮子还是比较全的哈,这里还是给大家安利一个组件:

  slider_button: ^0.6.0
SliderButton(
            boxShadow: BoxShadow(
              color: Colors.blue,
              blurRadius: 2,
            ),
            width: (MediaQuery.of(context).size.width - 56 - 16) / 2,
            height: 36,
            buttonSize: 20,
            radius: 18,
            alignLabel: Alignment(0.1, 0),
            buttonColor: Colors.white,
            backgroundColor: Colors.blue,
            shimmer: false,
            dismissible: false,
            label: Text(
              "滑动确认送达",
              style: TextStyle(fontSize: 12, color: Colors.white),
            ),
            icon: Center(
                child: Icon(
                  Icons.arrow_forward_ios,
                  color: Colors.blue,
                  size: 12.0,
                  semanticLabel: 'Text to announce in accessibility modes',
                )
            ),
            action: () {

            },
          ),

按钮中的各个元素需要根据实际情况来设置,如果设置不好的话按钮的样子就很丑啦。

6.插旗和更新位置信息


地图上标记位置,并实时更新位置信息是需要我们自己来写交互的,看如下方法:
1.添加大头针:

/// 添加大头针
  Future<void> addMarker() async {
    BMFCoordinate coordinate = BMFCoordinate(widget.latitude ?? 39.928617, widget.longitude ?? 116.40329);
    _getAddressFromLatLng().then((value) {
      BMFMarker marker = BMFMarker(
          position: coordinate,
          title: '配送员配送中',
          subtitle: value ?? '',
          identifier: 'flutter_marker',
          icon: 'resoures/route_detail_start.png');
      myMapController?.addMarker(marker);
      _marker = marker;
    });

    if (_timer == null) {
      _timer = Timer.periodic(Duration(milliseconds: 10000), (timer) async {
        reloadLocation();
      });
    }
  }

_getAddressFromLatLng是反地理编码,上面已经给出了代码。

2.更新大头针位置和地图的中心点

  Future<void> reloadLocation() async {
    dposition = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best);
    _getAddressFromLatLng();
    if (dposition != null) {
      print(dposition);
      BMFCoordinate  coordinate = BMFCoordinate(dposition?.latitude ?? 39.928617, dposition?.longitude ?? 116.40329);
      ///更新插旗的位置
      _marker.updatePosition(coordinate);
      ///设置地图中心点
      myMapController?.setCenterCoordinate(coordinate, true);
    }
  }

7.总结和页面完整代码


总的来说,flutter目前的轮子还是比较多的,很多复杂的功能都能够实现,要么官方提供了轮子,要么就是其他大佬写好的。
这个页面接本都是采用了其他开发者提供的组件来完成,这样看下来,功能的复杂度都降低了很多,这里只是给大家提供个思路,希望给大家能带来帮助。

这里提供下完整的代码:
引入库:

  slider_button: ^0.6.0
  flutter_baidu_mapapi_map: ^2.0.0
  permission_handler: ^5.0.1+1
  geolocator: 6.2.1
  geocoding: 1.0.1
  drag_container: 1.0.2

引入百度资源:

  assets:
    - resoures/
    - files/
    - resoures/bmflocaltileimage/16/
    - resoures/bmflocaltileimage/17/

这个大家参考百度的demo,把资源拿过来

页面类配送页面:

import 'dart:async';
import 'dart:io';
import 'package:drag_container/drag/drag_container.dart';
import 'package:flutter/material.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_map/sending_list_widget.dart';
import 'package:geolocator/geo
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodingFire

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值