用高德sdk做一个滴滴司机端的导航(高德自定义地图导航界面)

用高德sdk做一个滴滴司机端的导航。

主要的导航功能是在NaviFragment中。

效果如下:


image

下载apk:下载地址

扫一扫下载apk

下载apk图片.png

第一步:集成高德sdk

请看这篇文章
集成Android高德SDK

第二步:四个重要的类

1.AMapNaviView 导航地图控件,导航路线都是在这个上面绘制的

    //AMapNaviView一些重要方法
    //获取绘制路线所需的Amap类。
    AMapNaviView.getMap()。
    
    AMapNaviView有生命周期方法 需要我们和Activity或者Fragment的生命周期保持一致。
    
    AMapNaviView.onCreate(savedInstanceState)。在Activity的onCreate调用 在Fragment的onViewCreate调用
    
    AMapNaviView.onResume();   在Activity或者Fragment的onCreate中调用
    
    AMapNaviView.onPause();    在Activity或者Fragment的onPause中调用

    AMapNaviView.onDestory();  在Activity或者Fragment的onDestory中调用
    
    提示:AMapNaviView是没有onStop方法的,所以不用写。

2. RouteOverLay 用来在AMapNaviView上绘制导航的路线的类

   //RouteOverLay一些重要方法
   //根据数据创建一个RouteOverLay
   RouteOverLay routeOverLay = new RouteOverLay(Amap, AMapNaviPath, Context);
   //添加到地图上。
   RouteOverLay.addToMap();

3. AMapNavi 导航功能类。(这个类是单例模式的)

    //主要用来发起导航,可以向AMapNavi设置监听器监听导航中一些信息回调
    //AMapNavi一些重要方法 
    //计算驾车路径(包含起点)。
    AMapNavi.calculateDriveRoute(from, to,wayPoints,strategy); 
    // 添加导航事件回调监听。
    AMapNavi.addAMapNaviListener(listener);
    //开始导航。
    AMapNavi.startNavi(type);

4. AMapNaviListener 导航信息监听类

    //可以通过AMapNavi.addAMapNaviListener(AMapNaviListener)
    //AMapNaviListener有很多回调方法。这里介绍两个非常重要的回调方法。

    //路线计算成功的回调方法。我们需要在这里做绘制导航路线。
    public void onCalculateRouteSuccess(AMapCalcRouteResult aMapCalcRouteResult)
    {
        
    }
    //路线计算失败的回调方法。我们需要在这里失败的逻辑  比如显示一个按钮 告诉用户重试,重试也是调用AMapNavi.calculateDriveRoute(); 
    public void onCalculateRouteFailure(AMapCalcRouteResult aMapCalcRouteResult){
        
    }

四种触发AMapNaviListener的回调方法onCalculateRouteSuccess 或onCalculateRouteFailure的情况

  • 第一种情况: 我们主动调用AMapNavi.calculateDriveRoute()方法。前面已经介绍过了。
  • 第二种情况: 我们主动调用AMapNavi.switchParallelRoad()方法。(切换主路或辅路) AMapNaviListener 可以通过notifyParallelRoad(int parallelRoadType)告诉我们是在主路还是在辅路上。
  • 第三种情况: SDK内部通过AMapNaviListener的回调方法onReCalculateRouteForYaw()通知我们准备开始偏航了重新计算路线,
    这个时候也回调onCalculateRouteSuccess或onCalculateRouteFailure。

  • 第四种情况: SDK内部通过AMapNaviListener的回调方法onReCalculateRouteForTrafficJam()方法通知我们准备开始拥堵重新计算路线,
    这个时候也会回调onCalculateRouteSuccess或onCalculateRouteFailure。
    (非常拥堵重新计算路线这种况其实非常少见)

第三步: 如何使用这4个类。先写个简单的流程。

//获取AMapNaviView地图view
    AMapNaviView naviView=findViewById(R.id.naviView);
    AMapNaviViewOptions options = naviView.getViewOptions();


    //关闭自动绘制路线(如果你想自行绘制路线的话,必须关闭!!!)非常重要
    options.setAutoDrawRoute(false);
    //设置导航UI是否显示
    options.setLayoutVisible(false);
    
    //重新设置一下。
    naviView.setViewOptions(options);


    mAMapNavi=AMapNavi.getInstance(getContext);
   //向AMapNavi设置监听器。
    mAMapNavi.addAMapNaviListener(new AMapNaviListener() {
        @Override
        public void onCalculateRouteSuccess(AMapCalcRouteResult aMapCalcRouteResult) {
            //返回路线成功 这里通过AMapCalcRouteResult绘制路线
            
            //获取RouteOverLay所需要的Amap 如果要把路线绘制到AMapNaviView 请获取AMapNaviView的Amap
            aMap= AMapNaviView.getMap()
            
            //获取返回路线的数组routIDs aMapCalcRouteResult会返回一条或者多条路线。
            //ps:多条路线是用来做多路线选择的功能但是这里我们只做简单导航。所以我们只绘制一条。
            int[] routIds = aMapCalcRouteResult.getRouteid();
            int routeId=routIds[0].
            //通过routeId获取AMapNaviPath数据。
            AMapNaviPath aMapNaviPath=AMapNavi.getNaviPaths().get(routeId);
            //然后就可以创建RouteOverLay了
            RouteOverLay routeOverLay = new RouteOverLay(aMap, aMapNaviPath, context);
            
            
            
            //添加到AMapNaviView上。
            routeOverLay.addToMap();
            
            
            //绘制路线成功后。调用startNavi开始导航。
            //当然你也可以在别的地方调用  AMapNavi.startNavi(); //但是一定要在onCalculateRouteSuccess之后调用。
            mAMapNavi.startNavi();
    
        }

        @Override
        public void onCalculateRouteFailure(AMapCalcRouteResult aMapCalcRouteResult) {
            //路线计算失败的回调方法。我们需要在这里做失败的逻辑  比如显示一个按钮 告诉用户重试,重试也是重新调用AMapNavi.calculateDriveRoute(); 
            ....
        }
        
    })
    
     //计算驾车路径(包含起点)。会回调 onCalculateRouteSuccess或 onCalculateRouteFailure方法。
     AMapNavi.calculateDriveRoute();
     

第四步: 导航信息的显示

导航信息:包括剩余公里 预估时间等 需要我们展现出来如下图。

导航效果图.png

其实这些信息我们只需要到 AMapNaviListener 去实现 onNaviInfoUpdate(NaviInfo naviInfo) 就可以拿到

代码如下:

    public void onNaviInfoUpdate(NaviInfo naviInfo) {
        if (null != naviInfo) {
            //获取当前路段剩余距离
            int distance =naviInfo.getCurStepRetainDistance();
            //下一个街道名称
            String roadName = naviInfo.getNextRoadName();
            //获取路线剩余距离(总的路程剩余距离)
            int allDitance =naviInfo.getPathRetainDistance(); 
            //获取路线剩余时间(总的路程剩余时间)
            String allTime = naviInfo.getPathRetainTime()
        
            //获取导航转向图标类型
            int iconType=naviInfo.getIconType()
        }

实景图与模型图。

什么是实景图和模型图看下面的图片大家就明白了

实景图和模型图.png

实景图和模型图的也是 需要在AMapNaviListener 中实现下面的方法就可以实现了


   首先我们需要在
    AMapNaviViewOptions options = getNaviView().getViewOptions();
    //设置是否自动显示模型图 这里我们设置为false 
    options.setModeCrossDisplayShow(false);
    AMapNaviView.setViewOptions(options);
    
    @Override
    public void showCross(AMapNaviCross aMapNaviCross) {
        //实景图显示 回调

        //展示实景图
        zmLittleInIntersectionView.setImageBitmap(aMapNaviCross.getBitmap());


    }

    @Override
    public void hideCross() {
        //实景图隐藏 回调
  
       
    }

    @Override
    public void showModeCross(AMapModelCross aMapModelCross) {
     
        //模型图显示  回调

        //展示模型图
        modeCrossOverlay.createModelCrossBitMap(aMapModelCross.getPicBuf1(), new AMapModeCrossOverlay.OnCreateBitmapFinish() {
            @Override
            public void onGenerateComplete(Bitmap bitmap, int i) {
                zmLittleInIntersectionView.setImageBitmap(bitmap);
            }
        });

    }

    @Override
    public void hideModeCross() {
    
        //模型图隐藏 回调
        
    }

锁定自车与全览。

什么是锁定自车和全览

请看下图:

锁定自车模式到全览模式.gif

可以看到 当我们点击全览按钮的时候调用 displayOverview()方法 从锁定自车模式进入了全览路线的模式
点击定位按钮的时候 调用 recoverLockMode()方法进入锁车模式

方法如下


    //恢复锁车状态:用于用户主动恢复之前的导航锁车状态(比如从全览画面,挪动地图后画面返回)
    AMapNaviView.recoverLockMode();
         
  
    //全览可以通过下面的方式设置全览方法的上下左右的范围
    AMapNaviViewOptions options = getNaviView().getViewOptions();
    RouteOverlayOptions routeOverlayOptions = new RouteOverlayOptions();
    //int left, int top, int right, int bottom
    routeOverlayOptions.setRect(new Rect(100, 400, 100, 100));
    options.setRouteOverlayOptions(routeOverlayOptions);
    AMapNaviView.setViewOptions(options);
    //
    
    //全览模式  展示全览:成功算路获得路径之后,可将地图缩放到完全展示该路径
    AMapNaviView.displayOverview();

导航路线上箭头和走过的灰色路线。

请看下图:

箭头和走过的灰色路线.png

这两个效果的实现都要使用 RouteOverLay中的drawArrow方法和 updatePolyline方法
并且要与AMapNaviListener 中的
onNaviInfoUpdate(NaviInfo naviInfo),
onLocationChange(AMapNaviLocation aMapNaviLocation)
配合使用

代码如下:



    @Override
    public void onNaviInfoUpdate(NaviInfo naviInfo) {
        List<NaviLatLng> naviLatLngList = routeOverLay.getArrowPoints(naviInfo.getCurStep());
        //画导航的箭头。
        routeOverLay.drawArrow(naviLatLngList);
    }

    @Override
    public void onLocationChange(AMapNaviLocation aMapNaviLocation) {
        super.onLocationChange(aMapNaviLocation);
        //画走过的灰色路线
        routeOverLay.updatePolyline(naviLocation);
    }



结束

在这里我大概介绍完了总体流程,

其实还有一个切换主路辅路功能没介绍,

当然还有很多细节问题,可以看下代码我写了很多注释。很简单

高德导航sdk文档

或者看下这个工程的代码,主要代码在NaviFragment中。

源码github

谢谢大家


推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 128,919评论 19 550
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 6,946评论 1 38
  • 致敬那一年的仙剑奇侠传 十年前,一部仙剑横空出世,在中国广泛的影视市场开辟了仙侠剧,从此将众多的一代人带入...
    她说她说阅读 17评论 0 0
  • 今早醒来,忘记第一时间量体温,于是在闹钟响过之后为了保持镇静能使体温数据准确而耽误了几分钟。父亲过来敲我的房门,提...
    野籽小姐阅读 20评论 1 1
  • 1号,男,唐先生,30岁 2号,女,方女士,36岁 3号,男,方唐,15岁 4号,女,李婷,15岁 不重要的人物有...
    小兔儿酱阅读 14评论 0 0