android 高德地图 自定义图层 路线规划 自定义marker

最近接到了一个新需求 计划做路线提示 由于个性化程度很高 与原地图差异较大 我选择了自定义地图和路线规划相机和的方式 

先看效果图 


效果图

首先要点 基本地图显示 定位蓝点 路线规划 自定义路线规划图层(高德已开源) 自定义marker 测距等 功能部分官方网的文档并不是很清晰 我在这里整理一下 我所用的流程

第一 先配置高德环境 自己去高德官网看 按文档来就可以了

第二 初始化地图

map_view = (MapView) findViewById(R.id.map_view); 

map_view.onCreate(savedInstanceState); 

if (map_view!=null){ 

aMap = map_view.getMap(); 

}

设置定位蓝点

MyLocationStyle myLocationStyle; 

myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)如果不设置myLocationType,默认也会执行此种模式。 

myLocationStyle.interval(2000); //设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。 

aMap.getUiSettings().setMyLocationButtonEnabled(false);//设置默认定位按钮是否显示,非必需设置。 

aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。 

// myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)默认执行此种模式。 

myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);//连续定位、蓝点不会移动到地图中心点,定位点依照设备方向旋转,并且蓝点会跟随设备移动。 

myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.mipmap.map_ownerlocation_img)); 

myLocationStyle.showMyLocation(true);

    aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style

    aMap.setMapType(AMap.MAP_TYPE_NAVI);

模拟地点 并规划路线

////////////////////路线规划//////////////////////

    start = new LatLonPoint(30.291779,120.040998);

    end = new LatLonPoint(30.406169,120.305117);

    final LatLonPoint way1 = new LatLonPoint(30.270999,120.163277);

    final LatLonPoint way2 = new LatLonPoint(30.291124,120.212892);

    wayPointList.add(way1);

    wayPointList.add(way2);

    routeSearch = new RouteSearch(this);

    routeSearch.setRouteSearchListener(this);

    // fromAndTo包含路径规划的起点和终点,drivingMode表示驾车模式

    // 第三个参数表示途经点(最多支持16个),第四个参数表示避让区域(最多支持32个),第五个参数表示避让道路

    RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(start, end);

    RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DrivingDefault,wayPointList, null, “”); 

routeSearch.calculateDriveRouteAsyn(query);

//////////////////当前位置监听//////////////////

    aMap.setOnMyLocationChangeListener(new AMap.OnMyLocationChangeListener() {

        @Override

        public void onMyLocationChange(Location location) {

        }

    })


自定义路线规划图层 高德sdk 5.0版本以后 就不在提供overlay包 但是官方demo 中会有overlay 包 如有需要你可以直接过去拷贝 有一些小地方需要修改 注意下

@Override 

public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) { 

if (i==1000){// 路线规划成功 

if (driveRouteResult!=null&&driveRouteResult.getPaths()!=null&&driveRouteResult.getPaths().size()>0){ 

DrivePath drivePath = driveRouteResult.getPaths().get(0); 

aMap.clear();// 清理地图上的所有覆盖物 

// 定义图层 

DrivingRouteOverlay drivingRouteOverlay = new DrivingRouteOverlay(MapActivity.this, aMap, drivePath, 

driveRouteResult.getStartPos(), 

driveRouteResult.getTargetPos(),wayPointList); 

drivingRouteOverlay.setNodeIconVisibility(false);//隐藏转弯的节点 

drivingRouteOverlay.addToMap(); 

drivingRouteOverlay.zoomToSpan(); 

aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(new 

LatLngBounds( 

new LatLng(start.getLatitude(),start.getLongitude()), 

new LatLng(end.getLatitude(),end.getLongitude())),50));

        }

    }else {// 路线规划失败

        Toast.makeText(MapActivity.this, "无可用路线", Toast.LENGTH_SHORT).show();

    }

}

自定义图层类

import java.util.ArrayList; import java.util.List;

import android.content.Context; import android.graphics.Bitmap; import 

android.graphics.BitmapFactory; import android.graphics.Color; import 

android.graphics.drawable.Drawable; import android.os.Parcel; import 

android.util.Log; import android.view.LayoutInflater; import 

android.view.View; import android.widget.LinearLayout;

import com.amap.api.maps.AMap; import 

com.amap.api.maps.model.BitmapDescriptor; import 

com.amap.api.maps.model.BitmapDescriptorFactory; import 

com.amap.api.maps.model.LatLng; import 

com.amap.api.maps.model.LatLngBounds; import 

com.amap.api.maps.model.Marker; import 

com.amap.api.maps.model.MarkerOptions; import 

com.amap.api.maps.model.PolylineOptions; import 

com.amap.api.services.core.LatLonPoint; import 

com.amap.api.services.route.DrivePath; import 

com.amap.api.services.route.DriveStep; import 

com.amap.api.services.route.TMC; import com.free_ride.yiwei.R; import 

com.free_ride.yiwei.mvputils.HttpUtils; import 

com.free_ride.yiwei.personal.AppManager; import 

com.free_ride.yiwei.pinchexin.MapActivity; import 

com.free_ride.yiwei.utils.InternetAddressUtis; import 

com.free_ride.yiwei.views.RoundImageView; import 

com.squareup.picasso.Picasso;

import org.xutils.common.Callback; import org.xutils.x;

/导航路线图层类。 */

public class DrivingRouteOverlay extends RouteOverlay{

private DrivePath drivePath; 

private List throughPointList; 

private List throughPointMarkerList = new ArrayList(); 

private boolean throughPointMarkerVisible = true; 

private List tmcs; 

private PolylineOptions mPolylineOptions; 

private PolylineOptions mPolylineOptionscolor; 

private Context mContext; 

private boolean isColorfulline = true; 

private float mWidth = 25; 

private List mLatLngsOfPath;

private ArrayListiconList = new ArrayList();

public void setIsColorfulline(boolean iscolorfulline) { 

this.isColorfulline = iscolorfulline; }

/** 

* 根据给定的参数,构造一个导航路线图层类对象。 

* @param amap 地图对象。 

* @param path 导航路线规划方案。 

* @param context 当前的activity对象。 

*/ 

public DrivingRouteOverlay(Context context, AMap amap, DrivePath path, 

LatLonPoint start, LatLonPoint end, List throughPointList) { 

super(context); 

mContext = context; 

mAMap = amap; 

this.drivePath = path; 

startPoint = toLatLon(start); 

endPoint = toLatLon(end); 

this.throughPointList = throughPointList; 

}

public float getRouteWidth() {

    return mWidth;

}

/**

* 设置路线宽度

*

* @param mWidth 路线宽度,取值范围:大于0

*/

public void setRouteWidth(float mWidth) {

    this.mWidth = mWidth;

}

/**

* 添加驾车路线添加到地图上显示。

*/  public void addToMap() {        initPolylineOptions();

    try {

        if (mAMap == null) {

            return;

        }

        if (mWidth == 0 || drivePath == null) {

            return;

        }

        mLatLngsOfPath = new ArrayList();

        tmcs = new ArrayList();

        List drivePaths = drivePath.getSteps();

        mPolylineOptions.add(startPoint);

        for (DriveStep step : drivePaths) {

            List latlonPoints = step.getPolyline();

            List tmclist = step.getTMCs();

            tmcs.addAll(tmclist);

            addDrivingStationMarkers(step, convertToLatLng(latlonPoints.get(0)));

            for (LatLonPoint latlonpoint : latlonPoints) {

              mPolylineOptions.add(convertToLatLng(latlonpoint));

              mLatLngsOfPath.add(convertToLatLng(latlonpoint));

          }

        }

        mPolylineOptions.add(endPoint);

        if (startMarker != null) {

            startMarker.remove();

            startMarker = null;

        }

        if (endMarker != null) {

            endMarker.remove();

            endMarker = null;

        }

        addStartAndEndMarker();

        addThroughPointMarker();

        if (isColorfulline && tmcs.size()>0 ) {

          colorWayUpdate(tmcs);

          showcolorPolyline();            }else {

          showPolyline();            }           

    } catch (Throwable e) {

      e.printStackTrace();

    }

}


/** 

* 初始化线段属性 

*/ 

private void initPolylineOptions() { 

mPolylineOptions = null; 

mPolylineOptions = new PolylineOptions(); 

mPolylineOptions.color(getDriveColor()).width(getRouteWidth()); 

}

private void showPolyline() {

    addPolyLine(mPolylineOptions);

}

private void showcolorPolyline() {

  addPolyLine(mPolylineOptionscolor);

      }

/**

* 根据不同的路段拥堵情况展示不同的颜色

*

* @param tmcSection

*/

private void colorWayUpdate(List tmcSection) {

    if (mAMap == null) {

        return;

    }

    if (tmcSection == null || tmcSection.size() <= 0) {

        return;

    }

    TMC segmentTrafficStatus;

    mPolylineOptionscolor = null;

    mPolylineOptionscolor = new PolylineOptions();

    mPolylineOptionscolor.width(getRouteWidth());

    List colorList = new ArrayList();

    mPolylineOptionscolor.add(startPoint);

    mPolylineOptionscolor.add(toLatLon(tmcSection.get(0).getPolyline().get(0)));

    colorList.add(getDriveColor());

    for (int i = 0; i < tmcSection.size(); i++) {

      segmentTrafficStatus = tmcSection.get(i);

      int color = getcolor(segmentTrafficStatus.getStatus());

      List mployline = segmentTrafficStatus.getPolyline(); 

mployline.size(); j++) { 

mPolylineOptionscolor.add(toLatLon(mployline.get(j))); 

colorList.add(color); } } 

mPolylineOptionscolor.add(endPoint); 

colorList.add(getDriveColor()); 

mPolylineOptionscolor.colorValues(colorList); 

}

private int getcolor(String status) {

  if (status.equals("畅通")) {

      return Color.GREEN;        } else if (status.equals("缓行")) {

      return Color.YELLOW;      } else if (status.equals("拥堵")) {          return Color.RED;      } else if (status.equals("严重拥堵")) {            return Color.parseColor(“#990033”); } else { return 

Color.parseColor(“#537edc”); } }

public LatLng convertToLatLng(LatLonPoint point) { 

return new LatLng(point.getLatitude(),point.getLongitude()); }

/**

* @param driveStep

* @param latLng

*/

private void addDrivingStationMarkers(DriveStep driveStep, LatLng latLng) {

    addStationMarker(new MarkerOptions()

            .position(latLng)

            .title("\u65B9\u5411:" + driveStep.getAction()

                    + "\n\u9053\u8DEF:" + driveStep.getRoad())

            .snippet(driveStep.getInstruction()).visible(nodeIconVisible)

            .anchor(0.5f, 0.5f).icon(getDriveBitmapDescriptor()));

}

@Override

protected LatLngBounds getLatLngBounds() {

    LatLngBounds.Builder b = LatLngBounds.builder();

    b.include(new LatLng(startPoint.latitude, startPoint.longitude));

    b.include(new LatLng(endPoint.latitude, endPoint.longitude));

    if (this.throughPointList != null && this.throughPointList.size() > 0) {

        for (int i = 0; i < this.throughPointList.size(); i++) {

            b.include(new LatLng(

                    this.throughPointList.get(i).getLatitude(),

                    this.throughPointList.get(i).getLongitude()));

        }

    }

    return b.build();

}

public void setThroughPointIconVisibility(boolean visible) {

    try {

        throughPointMarkerVisible = visible;

        if (this.throughPointMarkerList != null

                && this.throughPointMarkerList.size() > 0) {

            for (int i = 0; i < this.throughPointMarkerList.size(); i++) {

                this.throughPointMarkerList.get(i).setVisible(visible);

            }

        }

    } catch (Throwable e) {

        e.printStackTrace();

    }

}

// 添加marker

private void addThroughPointMarker() {

    if (this.throughPointList != null && this.throughPointList.size() > 0) {

        LatLonPoint latLonPoint = null;

        iconList.add(BitmapDescriptorFactory.fromResource(R.mipmap.map_end_img));

        for (int i = 0; i < this.throughPointList.size(); i++) {

            latLonPoint = this.throughPointList.get(i);

            if (latLonPoint != null) {

                throughPointMarkerList.add(mAMap.addMarker(initMarkerObject(latLonPoint,i)));

            }

        }

    }

}

    // 初始化marker  自定义marker 样式 下main会给出map_custom_marker_img  xml 文件

private MarkerOptions initMarkerObject(LatLonPoint latLonPoint, int i) {

    View inflate = LayoutInflater.from(AppManager.getAppManager().currentActivity()).inflate(R.layout.map_custom_marker_img,null); 

RoundImageView roundImg = (RoundImageView) inflate.findViewById(R.id.map_custom_marker); 

roundImg.setImageBitmap(BitmapFactory.decodeResource(AppManager.getAppManager().currentActivity().getResources(),R.mipmap.map_passheand_one)); 

MarkerOptions options = null;

if (i%2==0){

        options = new MarkerOptions();

        options.position(new LatLng(latLonPoint.getLatitude(),latLonPoint.getLongitude()))

                .visible(throughPointMarkerVisible)

                .icon(BitmapDescriptorFactory.fromBitmap(convertViewToBitmap(inflate)))

                .autoOverturnInfoWindow(true)

                .title("距离"+(i+1)+"还有"+(calculateDistance(this.startPoint,newLatLng(throughPointList.get(i).getLatitude(),throughPointList.get(i).getLongitude())))+”米”); 

}else { options = new MarkerOptions();

        options.position(new LatLng(latLonPoint.getLatitude(),latLonPoint.getLongitude()))

                .visible(throughPointMarkerVisible)

                .icon(BitmapDescriptorFactory.fromBitmap(convertViewToBitmap(inflate)))

                .autoOverturnInfoWindow(true)

                .title("距离"+(i+1)+"还有"+(calculateDistance(this.startPoint,newLatLng(throughPointList.get(i).getLatitude(),throughPointList.get(i).getLongitude())))+”米”); 

} return options;

}

/**

* view 转为 bitmap 对象

* @param view

* @return

*/

public static Bitmap convertViewToBitmap(View view) {

    view.destroyDrawingCache();

    view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),

            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());

    view.setDrawingCacheEnabled(true);

    return view.getDrawingCache(true);

}

private BitmapDescriptor getThroughPointBitDes() {

  return BitmapDescriptorFactory.fromResource(R.mipmap.pass_head);

}

/**

* 获取两点间距离

*

* @param start

* @param end

* @return

*/

public static int calculateDistance(LatLng start, LatLng end) {

    double x1 = start.longitude;

    double y1 = start.latitude;

    double x2 = end.longitude;

    double y2 = end.latitude;

    return calculateDistance(x1, y1, x2, y2);

}

public static int calculateDistance(double x1, double y1, double x2, double y2) {

    final double NF_pi = 0.01745329251994329; // 弧度 PI/180

    x1 *= NF_pi;

    y1 *= NF_pi;

    x2 *= NF_pi;

    y2 *= NF_pi;

    double sinx1 = Math.sin(x1);

    double siny1 = Math.sin(y1);

    double cosx1 = Math.cos(x1);

    double cosy1 = Math.cos(y1);

    double sinx2 = Math.sin(x2);

    double siny2 = Math.sin(y2);

    double cosx2 = Math.cos(x2);

    double cosy2 = Math.cos(y2);

    double[] v1 = new double[3];

    v1[0] = cosy1 * cosx1 - cosy2 * cosx2;

    v1[1] = cosy1 * sinx1 - cosy2 * sinx2;

    v1[2] = siny1 - siny2;

    double dist = Math.sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);

    return (int) (Math.asin(dist / 2) * 12742001.5798544);

}

//获取指定两点之间固定距离点

public static LatLng getPointForDis(LatLng sPt, LatLng ePt, double dis) {

    double lSegLength = calculateDistance(sPt, ePt);

    double preResult = dis / lSegLength;

    return new LatLng((ePt.latitude - sPt.latitude) * preResult + sPt.latitude, (ePt.longitude - sPt.longitude) * preResult +sPt.longitude); 

/** 

* 去掉DriveLineOverlay上的线段和标记。 

*/ 

@Override 

public void removeFromMap() { 

try { 

super.removeFromMap(); 

if (this.throughPointMarkerList != null 

&& this.throughPointMarkerList.size() > 0) { 

for (int i = 0; i < this.throughPointMarkerList.size(); i++) { 

this.throughPointMarkerList.get(i).remove(); 

this.throughPointMarkerList.clear(); 

} catch (Throwable e) { 

e.printStackTrace(); 

}

/**

* 把LatLonPoint对象转化为LatLon对象

*/

public static LatLng toLatLon(LatLonPoint lonPoint){

    return new LatLng(lonPoint.getLatitude(),lonPoint.getLongitude());

} }

我的需求是水滴型内嵌套圆形头像的marker 

map_custom_marker_img 文件

到此就完结了 如有疑问 欢迎留言和私信

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335

推荐阅读更多精彩内容

  • android 基于高德地图的轨迹回放 前段时间公司项目有一个需求,就是需要看到设备上传之后的轨迹路线,并且可以实...
    假装成熟的冯先生阅读 8,717评论 4 8
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,025评论 0 2
  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,260评论 0 10
  • 有的人来到身边,成了朋友,有的人来到身边,成了仇人。 有的人来到身边,成了恋人,有的人离开身边,成了前任。 有的人...
    楼台花舍阅读 241评论 2 8
  • 闭上您的眼睛,放空再放空,请聆听萍儿为您诵读! 等你歌唱(点开收听) 我好想唱歌但至今都没唱过却把时间花在调理乐器...
    蒋光头jL94430阅读 445评论 48 78