最近接到了一個新需求 計劃做路線提示 由于個性化程度很高 與原地圖差異較大 我選擇了自定義地圖和路線規(guī)劃相機和的方式?
先看效果圖?
首先要點 基本地圖顯示 定位藍點 路線規(guī)劃 自定義路線規(guī)劃圖層(高德已開源) 自定義marker 測距等 功能部分官方網的文檔并不是很清晰 我在這里整理一下 我所用的流程
第一 先配置高德環(huán)境 自己去高德官網看 按文檔來就可以了
第二 初始化地圖
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);//連續(xù)定位、且將視角移動到地圖中心點贤牛,定位點依照設備方向旋轉惋鹅,并且會跟隨設備移動。(1秒1次定位)如果不設置myLocationType殉簸,默認也會執(zhí)行此種模式闰集。?
myLocationStyle.interval(2000); //設置連續(xù)定位模式下的定位間隔,只在連續(xù)定位模式下生效般卑,單次定位模式下不會生效武鲁。單位為毫秒。?
aMap.getUiSettings().setMyLocationButtonEnabled(false);//設置默認定位按鈕是否顯示蝠检,非必需設置沐鼠。?
aMap.setMyLocationEnabled(true);// 設置為true表示啟動顯示定位藍點,false表示隱藏定位藍點并不進行定位叹谁,默認是false饲梭。?
// myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//連續(xù)定位、且將視角移動到地圖中心點焰檩,定位點依照設備方向旋轉憔涉,并且會跟隨設備移動。(1秒1次定位)默認執(zhí)行此種模式析苫。?
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);//連續(xù)定位兜叨、藍點不會移動到地圖中心點寂曹,定位點依照設備方向旋轉遭贸,并且藍點會跟隨設備移動。?
myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.mipmap.map_ownerlocation_img));?
myLocationStyle.showMyLocation(true);
? ? aMap.setMyLocationStyle(myLocationStyle);//設置定位藍點的Style
? ? aMap.setMapType(AMap.MAP_TYPE_NAVI);
模擬地點 并規(guī)劃路線
////////////////////路線規(guī)劃//////////////////////
? ? 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包含路徑規(guī)劃的起點和終點,drivingMode表示駕車模式
? ? // 第三個參數(shù)表示途經點(最多支持16個)白华,第四個參數(shù)表示避讓區(qū)域(最多支持32個)屯烦,第五個參數(shù)表示避讓道路
? ? RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(start, end);
? ? RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DrivingDefault,wayPointList, null, “”);?
routeSearch.calculateDriveRouteAsyn(query);
//////////////////當前位置監(jiān)聽//////////////////
? ? aMap.setOnMyLocationChangeListener(new AMap.OnMyLocationChangeListener() {
? ? ? ? @Override
? ? ? ? public void onMyLocationChange(Location location) {
? ? ? ? }
? ? })
自定義路線規(guī)劃圖層 高德sdk 5.0版本以后 就不在提供overlay包 但是官方demo 中會有overlay 包 如有需要你可以直接過去拷貝 有一些小地方需要修改 注意下
@Override?
public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) {?
if (i==1000){// 路線規(guī)劃成功?
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);//隱藏轉彎的節(jié)點?
drivingRouteOverlay.addToMap();?
drivingRouteOverlay.zoomToSpan();?
aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(new?
LatLngBounds(?
new LatLng(start.getLatitude(),start.getLongitude()),?
new LatLng(end.getLatitude(),end.getLongitude())),50));
? ? ? ? }
? ? }else {// 路線規(guī)劃失敗
? ? ? ? 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; }
/**?
* 根據給定的參數(shù)茄靠,構造一個導航路線圖層類對象。?
*?
* @param amap 地圖對象屡久。?
* @param path 導航路線規(guī)劃方案吧雹。?
* @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 文件
到此就完結了 如有疑問 歡迎留言和私信