又有新需求 所以继续地图开发 这里记录两点 一是拖动定位 二是对多点路线规划不同路段设置颜色 下面给出效果图看一下 再上干货
先推荐一个拾取经纬度工具 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 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 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 throughPointList;
private List throughPointMarkerList = new ArrayList();
private boolean throughPointMarkerVisible = true;
private PolylineOptions mPolylineOptions;
private boolean isColorfulline = true;
private float mWidth = 25;
private DriveStep startStep;
private DriveStep currentStep;
private List colors;
private List 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 throughPointList,
List colors,
List 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 drivePaths = drivePath.getSteps();
List colorList = new ArrayList<>();
mPolylineOptions.add(startPoint);
if (colors.size()!=0) {
colorList.add(colors.get(0));
}
boolean isadd = false;
for (DriveStep step : drivePaths){
List 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 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 stationMarkers = new ArrayList();
protected List allPolyLines = new ArrayList();
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