Android 高德地图之拖动定位、多点路线规划给路段设置不同颜色

又有新需求 所以继续地图开发 这里记录两点 一是拖动定位 二是对多点路线规划不同路段设置颜色 下面给出效果图看一下 再上干货
先推荐一个拾取经纬度工具 http://www.gpsspg.com/bs.htm

在这里插入图片描述

由于上传大小受限 gif就不上了

https://www.jianshu.com/p/f6821974e463 点击可查看效果

先说第一种效果 拖动定位 这个效果还是很简单的实现的
说一下思路
1 首先进入地图页要获得当前位置并显示在地图上
2 通过拖动地图 并获取地图中间点的位置 进行逆运算
3 将选中的点设置成地图中心点 并且显示具体的地址

下面上代码

(首先布局文件就不写了 有兴趣的可以根据效果图自己写一个 )

// 请求定位权限
requestPermissions();
// 添加地图变化监听
map.setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition cameraPosition) {

        }

        @Override
        public void onCameraChangeFinish(CameraPosition cameraPosition) {
            setMyLocationMapCenter(cameraPosition.target);
            boundsSearchPoi(cameraPosition.target,null);
        }
    });
// 定位回调
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
if (null != aMapLocation){
if (aMapLocation.getErrorInfo().equals("success")) {
city = aMapLocation.getCity();
setMyLocationMapCenter(new LatLng(aMapLocation.getLatitude(),aMapLocation.getLongitude()));
start = new LocationBean();
start.setAddress(aMapLocation.getAddress());
start.setCity(TextUtils.isEmpty(city) ? "" : city);
start.setLat(aMapLocation.getLatitude());
start.setLon(aMapLocation.getLongitude());
start_tv.setText((TextUtils.isEmpty(city) ? "" :city)+aMapLocation.getAddress());
}
}
}

// 将latlng 设置为地图中心点
private void setMyLocationMapCenter(LatLng latlng){
CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(new CameraPosition(latlng, 17, 30, 0));
map.moveCamera(cameraUpdate);

}
// 检索  可检索周边 也可检索具体的key
private void boundsSearchPoi(@Nullable LatLng target ,@Nullable String key) {
    PoiSearch.Query query = new PoiSearch.Query(TextUtils.isEmpty(key) ? "" : key, "01|02|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|99", TextUtils.isEmpty(city) ? "" : city);
    query.setPageSize(10);
    query.setDistanceSort(true);
    PoiSearch search = new PoiSearch(this, query);
    if (target != null){
        PoiSearch.SearchBound bound = new PoiSearch.SearchBound(new LatLonPoint(target.latitude, target.longitude), 100);
        search.setBound(bound);
    }
    search.setOnPoiSearchListener(this);
    search.searchPOIAsyn();
}
// 搜索回调
@Override
public void onPoiSearched(PoiResult poiResult, int i) {
if (i == 1000) {
if (poiResult != null && poiResult.getPois() != null && poiResult.getPois().size() > 0) {
setMyLocationMapCenter(new LatLng(poiResult.getPois().get(0).getLatLonPoint().getLatitude(),poiResult.getPois().get(0).getLatLonPoint().getLongitude()));
show(poiResult.getPois().get(0));
}
}
}

好了 剩下的就是显示了 方法已经给出

下面说第二个效果 不同路段设置颜色
首先做好路线规划并显示在地图上 我会给出两个自定义图层和一个acitivity 实现逻辑

由于并没有给出这个方法 我是根据导航的源码受到启发 得到实现的 有兴趣你可以看一下navi 的源码 RouteOvelay 这个类里有介绍 说不定你能得到过更好的实现方式

说说效果 可以设置不同路段不同颜色 自定义marker 视图 多点规划 重点是DrivingRouteOverlay图层类
艰苦历程就不说了 直接干货

// 路线规划UI
public class NadeNaviActivity extends Activity implements RouteSearch.OnRouteSearchListener {

private MapView navi_map;
private AMap map;
private List<LatLonPoint> wayPoints;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_nade_navi);
    initNaviView();
    navi_map.onCreate(savedInstanceState);
    map = navi_map.getMap();
    Bundle bundle = getIntent().getExtras();

    planRoute();
}

/**
 * 路线规划
 *
 */
private void planRoute() {
    wayPoints = new ArrayList<>(); // 经途点集合
    wayPoints.add(new LatLonPoint(30.2762654235,120.0383377075));
    wayPoints.add(new LatLonPoint(30.2833069287,120.0756740570));
    wayPoints.add(new LatLonPoint(30.2921266276,120.1679420471));

    //腾讯高德:30.2903479286,120.0114727020
    LatLonPoint startPoint = new LatLonPoint(30.2903479286, 120.0114727020);
    //腾讯高德:30.2891621114,120.2158355713
    LatLonPoint endPoint = new LatLonPoint(30.2891621114, 120.2158355713);
    RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(startPoint, endPoint);
    RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DRIVING_SINGLE_DEFAULT, wayPoints, null, "");
    RouteSearch routeSearch = new RouteSearch(this);
    routeSearch.setRouteSearchListener(this);
    routeSearch.calculateDriveRouteAsyn(query);

}

private void initNaviView() {
    navi_map = findViewById(R.id.navi_map);
}

@Override
protected void onResume() {
    super.onResume();
    navi_map.onResume();

}

@Override
protected void onDestroy() {
    super.onDestroy();
    navi_map.onDestroy();

}

@Override
protected void onPause() {
    super.onPause();
    navi_map.onPause();

}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    navi_map.onSaveInstanceState(outState);

}

@Override
public void onBusRouteSearched(BusRouteResult busRouteResult, int i) {

}

@Override
public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) {
    if (i == 1000) {
        if (map != null) {
            map.clear();
        }
        if (driveRouteResult != null && driveRouteResult.getPaths() != null && driveRouteResult.getPaths().size() > 0) {

            List<Integer> colors = new ArrayList<>(); // 色值集合
            colors.add(Color.parseColor("#0471b1"));
            colors.add(Color.parseColor("#78ccfd"));
            colors.add(Color.parseColor("#ff0000"));
            DrivingRouteOverlay routeOverlay = new DrivingRouteOverlay(this,
                    map, driveRouteResult.getPaths().get(0),
                    driveRouteResult.getStartPos(),
                    driveRouteResult.getTargetPos(),
                    wayPoints,colors,null);
            routeOverlay.setNodeIconVisibility(false);
            routeOverlay.setIsColorfulline(false);
            routeOverlay.setThroughPointIconVisibility(true);
            routeOverlay.removeFromMap();

            routeOverlay.addToMap(R.mipmap.start_img,R.mipmap.end_img, "");
            routeOverlay.zoomToSpan();
        }

    }
}

@Override
public void onWalkRouteSearched(WalkRouteResult walkRouteResult, int i) {

}

@Override
public void onRideRouteSearched(RideRouteResult rideRouteResult, int i) {

}
}

/**

导航路线图层类。
*/

public class DrivingRouteOverlay extends RouteOverlay {

private DrivePath drivePath;
private List<LatLonPoint> throughPointList;
private List<Marker> throughPointMarkerList = new ArrayList<Marker>();
private boolean throughPointMarkerVisible = true;
private PolylineOptions mPolylineOptions;
private boolean isColorfulline = true;
private float mWidth = 25;
private DriveStep startStep;
private DriveStep currentStep;
private List<Integer> colors;
private List<View> throughViews;

public void setIsColorfulline(boolean iscolorfulline) {
this.isColorfulline = iscolorfulline;
}

/**

根据给定的参数,构造一个导航路线图层类对象。
@param amap 地图对象。
@param path 导航路线规划方案。
@param context 当前的activity对象。
@param throughPointList 途经点 ## 途经点集合
@param colors 色值集 ## 长度必须和色值集合途经点集合长度一致
@param throughViews 途径点marker视图 ## 途径点marker视图长度必须和途经点集合长度一致
*/
public DrivingRouteOverlay(Context context, AMap amap, DrivePath path,
LatLonPoint start, LatLonPoint end,
List<LatLonPoint> throughPointList,
List<Integer> colors,
List<View> throughViews) {
super(context);
mAMap = amap;
this.drivePath = path;
startPoint = AMapUtil.convertToLatLng(start);
endPoint = AMapUtil.convertToLatLng(end);
this.throughPointList = throughPointList;
this.colors = colors;
this.throughViews = throughViews;
}

public float getRouteWidth() {
return mWidth;
}

/**

设置路线宽度
@param mWidth 路线宽度,取值范围:大于0
*/
public void setRouteWidth(float mWidth) {
this.mWidth = mWidth;
}
/**

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

@param startRes

@param endRes

@param color 色值
*/
public void addToMap(int startRes,int endRes,String color) {
int index = 0;
initPolylineOptions(color);
try {
if (mAMap == null) {
return;
}
if (mWidth == 0 || drivePath == null) {
return;
}
List<DriveStep> drivePaths = drivePath.getSteps();
List<Integer> colorList = new ArrayList<>();
mPolylineOptions.add(startPoint);
if (colors.size()!=0) {
colorList.add(colors.get(0));
}

 boolean isadd = false;
 for (DriveStep step : drivePaths){
     List<LatLonPoint> latlonPoints = step.getPolyline();
     for (LatLonPoint point:latlonPoints){
         mPolylineOptions.add(convertToLatLng(point));
         if (step.getAssistantAction().equals("到达途经地") && isadd == false) { // 到达第一个途径点
             if (startStep == null) {
                 startStep = step;
                 isadd = true; // 设置为开始添加
                 index++;
             }
         }else if (step.getAssistantAction().equals("到达途经地") && isadd == true) { // 到达第二个途径点
             if (startStep != null && startStep != step){
                 isadd = false; // 设置为开始恢复
                 startStep = null;
             }
         }
         int size = colors.size();
         if (index < size){
             colorList.add(colors.get(index));
         }
     }
 }
 mPolylineOptions.add(endPoint);
 if (colors.size()!=0) {
     colorList.add(colors.get(0));
 }
 mPolylineOptions.colorValues(colorList);
 if (startMarker != null) {
     startMarker.remove();
     startMarker = null;
 }
 if (endMarker != null) {
     endMarker.remove();
     endMarker = null;
 }
 addStartAndEndMarker(startRes,endRes);
 //addThroughPointMarker(throughViews);
 showPolyline();
} catch (Throwable e) {
e.printStackTrace();
}

}

/**

初始化线段属性
*/
private void initPolylineOptions(String color) {
mPolylineOptions = null;
mPolylineOptions = new PolylineOptions();

mPolylineOptions.width(getRouteWidth());
if (colors.size() == 0){
mPolylineOptions.color(getDriveColor(color));
}
}

private void showPolyline() {
addPolyLine(mPolylineOptions);
}

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(List<View> views) {
    if (this.throughPointList != null && this.throughPointList.size() > 0) {
        LatLonPoint latLonPoint = null;
        for (int i = 0; i < this.throughPointList.size(); i++) {
            latLonPoint = this.throughPointList.get(i);
            if (latLonPoint != null) {
                Marker marker = mAMap
                        .addMarker((new MarkerOptions())
                                .position(
                                        new LatLng(latLonPoint
                                                .getLatitude(), latLonPoint
                                                .getLongitude()))
                                .visible(throughPointMarkerVisible)
                                .title(""));
                marker.setIcon(BitmapDescriptorFactory.fromView(views.get(i)));
                throughPointMarkerList.add(marker);
            }
        }
    }
}

private BitmapDescriptor getThroughPointBitDes() {
    //return BitmapDescriptorFactory.fromResource(R.mipmap.amap_through);
    return BitmapDescriptorFactory.fromResource(R.mipmap.app_maplocation);

}

/**
 * 获取两点间距离
 *
 * @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();
    }
}
}

public class RouteOverlay {
protected List<Marker> stationMarkers = new ArrayList<Marker>();
protected List<Polyline> allPolyLines = new ArrayList<Polyline>();
protected Marker startMarker;
protected Marker endMarker;
protected LatLng startPoint;
protected LatLng endPoint;
protected AMap mAMap;
private Context mContext;
private Bitmap startBit, endBit, busBit, walkBit, driveBit;
protected boolean nodeIconVisible = true;

public RouteOverlay(Context context) {
    mContext = context;
}

/**
 * 去掉BusRouteOverlay上所有的Marker。
 * @since V2.1.0
 */
public void removeFromMap() {
    if (startMarker != null) {
        startMarker.remove();

    }
    if (endMarker != null) {
        endMarker.remove();
    }
    for (Marker marker : stationMarkers) {
        marker.remove();
    }
    for (Polyline line : allPolyLines) {
        line.remove();
    }
    destroyBit();
}

private void destroyBit() {
    if (startBit != null) {
        startBit.recycle();
        startBit = null;
    }
    if (endBit != null) {
        endBit.recycle();
        endBit = null;
    }
    if (busBit != null) {
        busBit.recycle();
        busBit = null;
    }
    if (walkBit != null) {
        walkBit.recycle();
        walkBit = null;
    }
    if (driveBit != null) {
        driveBit.recycle();
        driveBit = null;
    }
}
/**
 * 给起点Marker设置图标,并返回更换图标的图片。如不用默认图片,需要重写此方法。
 * @return 更换的Marker图片。
 * @since V2.1.0
 */
protected BitmapDescriptor getStartBitmapDescriptor(int startRes) {
    return BitmapDescriptorFactory.fromResource(startRes);
}
/**
 * 给终点Marker设置图标,并返回更换图标的图片。如不用默认图片,需要重写此方法。
 * @return 更换的Marker图片。
 * @since V2.1.0
 */
protected BitmapDescriptor getEndBitmapDescriptor(int endRes) {
    return BitmapDescriptorFactory.fromResource(endRes);
}
/**
 * 给公交Marker设置图标,并返回更换图标的图片。如不用默认图片,需要重写此方法。
 * @return 更换的Marker图片。
 * @since V2.1.0
 */
protected BitmapDescriptor getBusBitmapDescriptor() {
    return BitmapDescriptorFactory.fromResource(R.mipmap.amap_bus);
}
/**
 * 给步行Marker设置图标,并返回更换图标的图片。如不用默认图片,需要重写此方法。
 * @return 更换的Marker图片。
 * @since V2.1.0
 */
protected BitmapDescriptor getWalkBitmapDescriptor() {
    return BitmapDescriptorFactory.fromResource(R.mipmap.amap_man);
}

protected BitmapDescriptor getDriveBitmapDescriptor() {
    return BitmapDescriptorFactory.fromResource(R.mipmap.end_img);
}

protected void addStartAndEndMarker(int startRes,int endRes) {
    startMarker = mAMap.addMarker((new MarkerOptions())
            .position(startPoint).icon(getStartBitmapDescriptor(startRes))
            .title(""));

    endMarker = mAMap.addMarker((new MarkerOptions()).position(endPoint)
            .icon(getEndBitmapDescriptor(endRes)).title(""));
     mAMap.moveCamera(CameraUpdateFactory.newLatLngZoom(startPoint,
     getShowRouteZoom()));
}
/**
 * 移动镜头到当前的视角。
 * @since V2.1.0
 */
public void zoomToSpan() {
    if (startPoint != null) {
        if (mAMap == null) {
            return;
        }
        try {
            LatLngBounds bounds = getLatLngBounds();
            mAMap.animateCamera(CameraUpdateFactory
                    .newLatLngBounds(bounds, 100));
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}

protected LatLngBounds getLatLngBounds() {
    LatLngBounds.Builder b = LatLngBounds.builder();
    b.include(new LatLng(startPoint.latitude, startPoint.longitude));
    b.include(new LatLng(endPoint.latitude, endPoint.longitude));
    return b.build();
}
/**
 * 路段节点图标控制显示接口。
 * @param visible true为显示节点图标,false为不显示。
 * @since V2.3.1
 */
public void setNodeIconVisibility(boolean visible) {
    try {
        nodeIconVisible = visible;
        if (this.stationMarkers != null && this.stationMarkers.size() > 0) {
            for (int i = 0; i < this.stationMarkers.size(); i++) {
                this.stationMarkers.get(i).setVisible(visible);
            }
        }
    } catch (Throwable e) {
        e.printStackTrace();
    }
}

protected void addStationMarker(MarkerOptions options) {
    if(options == null) {
        return;
    }
    Marker marker = mAMap.addMarker(options);
    if(marker != null) {
        stationMarkers.add(marker);
    }
    
}

protected void addPolyLine(PolylineOptions options) {
    if(options == null) {
        return;
    }
    Polyline polyline = mAMap.addPolyline(options);
    if(polyline != null) {
        allPolyLines.add(polyline);
    }
}

protected float getRouteWidth() {
    return 18f;
}

protected int getWalkColor() {
    return Color.parseColor("#6db74d");
}

/**
 * 自定义路线颜色。
 * return 自定义路线颜色。
 * @since V2.2.1
 */
protected int getBusColor() {
    return Color.parseColor("#0471b1");
}

protected int getDriveColor() {
    return Color.parseColor("#78ccfd");
}
protected int getDriveDarkColor() {
    return Color.parseColor("#0471b1");
}
protected int getDriveColor(String color) {
    return Color.parseColor(color);
}

 protected int getShowRouteZoom() {
 return 15;
 }
}

好了 就这样么多 有疑问可以私信我 或者加我qq

发布了75 篇原创文章 · 获赞 81 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/Naide_S/article/details/84935293
今日推荐