Android 高德地圖中路線規劃繪製界面線路
下面代碼是根據很多的經緯度的點,繪製出直線的線路。比較死板
/**
* 繪製景區的路線
*/
private void setRouteInfo(List<ScenicSpotGuideBean.ScenicLineListBean.CoordinateListBean> data) {
List<LatLng> list = listToLatLng(data);
mAllLinePolyline = mAmap.addPolyline((new PolylineOptions())
//集合數據
.addAll(list)
//線的寬度
.width(20)
.setDottedLine(false) // 關閉虛線
.geodesic(true)
//顏色
.color(Color.argb(255, 36, 164, 255)));
}
大概效果是這樣的 ,是一個點到另一個點之間的直線繪製。
因爲這個比較死板,在線路中繪製這個比較不好,然後就有了另一種繪製,就是線路的繪製。
先上效果圖吧
因爲界面要有這樣的想過,所以直線繪製就不考慮了。
我這邊大概就是根據高德地圖中的線路搜索,搜索類型是數據駕車。進行異步搜索並且繪製。就可以出這樣的效果。
// 創建線路搜索對象
RouteSearch mRouteSearch = null;
// 對象進行初始化
mRouteSearch = new RouteSearch(this);
// 搜索監聽
mRouteSearch.setRouteSearchListener(mRouteSearchListener);
由於我這邊是繪製多條線路,我這邊是這樣做的。
private void SurfacePolyDaysLine() {
// 清除界面上之前繪製的線路
clearAllLineMarker();
// 所有線路需要將開始的線路經緯度放到這個集合中
List<LatLng> list = new ArrayList<>();
for (int j = 0; j < list.size() - 1; j++) { // 遍歷當前集合進行搜索線路
// 傳入當前線路的起點和終點座標,然後進行繪製
searchRouteResult(new LatLonPoint(list.get(j).latitude, list.get(j).longitude), new LatLonPoint(list.get(j + 1).latitude, list.get(j + 1).longitude));
}
// update map zoom
setMapBounds(list);
}
下面是搜索線路代碼
/**
* start search line
*/
public void searchRouteResult(LatLonPoint mStartPoint, LatLonPoint mEndPoint) {
// 傳入起點座標、終點座標
final RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(mStartPoint, mEndPoint);
// DriveRouteQuery 類型是駕車的路線搜索 DRIVING_SINGLE_SHORTEST 類型表示返回單個路線最短的數據集
RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DRIVING_SINGLE_SHORTEST, null, null, "");
// 開始異步搜索處理
mRouteSearch.calculateDriveRouteAsyn(query);
}
搜索監聽事件 ,將監聽到的線路進行繪製在界面上就可以了。
/**
* search line listener
*/
RouteSearch.OnRouteSearchListener mRouteSearchListener = new RouteSearch.OnRouteSearchListener() {
@Override
public void onBusRouteSearched(BusRouteResult busRouteResult, int i) {
// bus
}
@Override
public void onDriveRouteSearched(DriveRouteResult result, int errorCode) {
// driving
if (errorCode == AMapException.CODE_AMAP_SUCCESS) {
if (result != null && result.getPaths() != null) {
if (result.getPaths().size() > 0) {
DriveRouteResult mDriveRouteResult = result;
final DrivePath drivePath = mDriveRouteResult.getPaths().get(0);
if (drivePath == null) { // 表示返回的線路是空的情況,就不管
return;
}
// 自定義的一個繪製處理
SharedHomeDrivingRouteOverlay drivingRouteOverlay = new SharedHomeDrivingRouteOverlay(
SharedNavigationMapActivity.this, mAmap, drivePath,
mDriveRouteResult.getStartPos(),
mDriveRouteResult.getTargetPos(), null);
drivingRouteOverlay.setNodeIconVisibility(false); // 是否顯示節點圖標,這個裏面沒有設置所以沒有,也不需要顯示
drivingRouteOverlay.setIsColorfulline(false); // 是否顯示線路的交通狀態
drivingRouteOverlay.removeFromMap(); // 先進行移除掉
drivingRouteOverlay.addToMap(); // 添加到地圖上面
// drivingRouteOverlay.zoomToSpan(); // 根據線路的起點和終點自動縮放zoom值,顯示在屏幕的中間
} else if (result != null && result.getPaths() == null) {
}
} else {
}
} else {
}
}
@Override
public void onWalkRouteSearched(WalkRouteResult walkRouteResult, int i) {
// walk
}
@Override
public void onRideRouteSearched(RideRouteResult rideRouteResult, int i) {
// ride
}
};
自定義繪製線路界面,是根據高德地圖《3D地圖示例》中的出行路線規劃中的駕車路徑規劃更改所得的,如果想要了解更多可以去參考這個demo文件的代碼。
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
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 cn.xmzt.www.R;
import java.util.ArrayList;
import java.util.List;
/**
* 導航路線圖層類。
*/
public class SharedHomeDrivingRouteOverlay extends RouteOverlay{
private DrivePath drivePath;
private List<LatLonPoint> throughPointList;
private List<Marker> throughPointMarkerList = new ArrayList<Marker>();
private boolean throughPointMarkerVisible = true;
private List<TMC> tmcs;
private PolylineOptions mPolylineOptions;
private PolylineOptions mPolylineOptionscolor;
private Context mContext;
private boolean isColorfulline = true;
private float mWidth = 90;
private List<LatLng> mLatLngsOfPath;
public void setIsColorfulline(boolean iscolorfulline) {
this.isColorfulline = iscolorfulline;
}
/**
* 根據給定的參數,構造一個導航路線圖層類對象。
*
* @param amap 地圖對象。
* @param path 導航路線規劃方案。
* @param context 當前的activity對象。
*/
public SharedHomeDrivingRouteOverlay(Context context, AMap amap, DrivePath path,
LatLonPoint start, LatLonPoint end, List<LatLonPoint> throughPointList) {
super(context);
mContext = context;
mAMap = amap;
this.drivePath = path;
startPoint = AMapUtil.convertToLatLng(start);
endPoint = AMapUtil.convertToLatLng(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<LatLng>();
tmcs = new ArrayList<TMC>();
List<DriveStep> drivePaths = drivePath.getSteps();
for (DriveStep step : drivePaths) {
List<LatLonPoint> latlonPoints = step.getPolyline();
List<TMC> tmclist = step.getTMCs();
tmcs.addAll(tmclist);
addDrivingStationMarkers(step, convertToLatLng(latlonPoints.get(0)));
for (LatLonPoint latlonpoint : latlonPoints) {
mPolylineOptions.add(convertToLatLng(latlonpoint));
mLatLngsOfPath.add(convertToLatLng(latlonpoint));
}
}
if (startMarker != null) {
startMarker.remove();
startMarker = null;
}
if (endMarker != null) {
endMarker.remove();
endMarker = null;
}
addThroughPointMarker();
if (isColorfulline && tmcs.size()>0 ) {
// colorWayUpdate(tmcs);
colorWayUpdates(tmcs);
showcolorPolyline();
}else {
showPolyline();
}
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
* 初始化線段屬性
*/
private void initPolylineOptions() {
mPolylineOptions = null;
mPolylineOptions = new PolylineOptions();
mPolylineOptions.color(getDriveColor()).width(getRouteWidth());
Bitmap bitmap = (Bitmap) BitmapFactory.decodeResource(mContext.getResources(),R.drawable.map_line_info_green);
mPolylineOptions.setCustomTexture(BitmapDescriptorFactory.fromBitmap(bitmap));// TODO 如果要添加圖片的話 需要將setIsColorfulline 設置爲true纔會顯示
mPolylineOptions.width(getRouteWidth());
mPolylineOptions.setUseTexture(true);
}
private void showPolyline() {
addPolyLine(mPolylineOptions);
}
private void showcolorPolyline() {
addPolyLine(mPolylineOptionscolor);
}
/**
* 根據不同的路段擁堵情況展示不同的顏色
*
* @param tmcSection
*/
private void colorWayUpdate(List<TMC> tmcSection) {
if (mAMap == null) {
return;
}
if (tmcSection == null || tmcSection.size() <= 0) {
return;
}
TMC segmentTrafficStatus;
mPolylineOptionscolor = null;
mPolylineOptionscolor = new PolylineOptions();
Bitmap bitmap = (Bitmap) BitmapFactory.decodeResource(mContext.getResources(),R.drawable.map_line_info_green);
mPolylineOptionscolor.setCustomTexture(BitmapDescriptorFactory.fromBitmap(bitmap));// TODO 如果要添加圖片的話 需要將setIsColorfulline 設置爲true纔會顯示
mPolylineOptionscolor.width(getRouteWidth());
mPolylineOptionscolor.setUseTexture(true);
List<Integer> colorList = new ArrayList<Integer>();
mPolylineOptionscolor.add(AMapUtil.convertToLatLng(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<LatLonPoint> mployline = segmentTrafficStatus.getPolyline();
for (int j = 1; j < mployline.size(); j++) {
mPolylineOptionscolor.add(AMapUtil.convertToLatLng(mployline.get(j)));
colorList.add(color);
}
}
colorList.add(getDriveColor());
mPolylineOptionscolor.colorValues(colorList);
}
/**
* 根據不同的路段擁堵情況展示不同的顏色的圖片
*
* @param tmcSection
*/
private void colorWayUpdates(List<TMC> tmcSection) {
if (mAMap == null) {
return;
}
if (tmcSection == null || tmcSection.size() <= 0) {
return;
}
TMC segmentTrafficStatus;
mPolylineOptionscolor = null;
mPolylineOptionscolor = new PolylineOptions();
// Bitmap bitmap = (Bitmap) BitmapFactory.decodeResource(mContext.getResources(),R.drawable.custtexture_green);
// mPolylineOptionscolor.setCustomTexture(BitmapDescriptorFactory.fromBitmap(bitmap));// TODO 如果要添加圖片的話 需要將setIsColorfulline 設置爲true纔會顯示
// mPolylineOptionscolor.width(getRouteWidth());
// mPolylineOptionscolor.setUseTexture(true);
List<Integer> colorList = new ArrayList<Integer>();
List<BitmapDescriptor> list = new ArrayList<>();
int position = 0;
mPolylineOptionscolor.add(AMapUtil.convertToLatLng(tmcSection.get(0).getPolyline().get(0)));
list.add(BitmapDescriptorFactory.fromResource(getDriveColorRes()));
colorList.add(position);
position += 1;
for (int i = 0; i < tmcSection.size(); i++) {
segmentTrafficStatus = tmcSection.get(i);
int colorres = getcolorRes(segmentTrafficStatus.getStatus());
List<LatLonPoint> mployline = segmentTrafficStatus.getPolyline();
for (int j = 1; j < mployline.size(); j++) {
mPolylineOptionscolor.add(AMapUtil.convertToLatLng(mployline.get(j)));
list.add(BitmapDescriptorFactory.fromResource(colorres));
colorList.add(position);
position += 1;
}
}
list.add(BitmapDescriptorFactory.fromResource(getDriveColorRes()));
colorList.add(position);
mPolylineOptionscolor.setCustomTextureList(list);
mPolylineOptionscolor.setCustomTextureIndex(colorList);
mPolylineOptionscolor.width(getRouteWidth());
mPolylineOptionscolor.setUseTexture(true);
}
private int getcolor(String status) {
if (status.equals("暢通")) { // 暢通情況下 綠色顯示
return Color.parseColor("#11BA1F");
} else if (status.equals("緩行")) { // 緩行情況下 黃色顯示
return Color.parseColor("#FFAD37");
} else if (status.equals("擁堵")) { // 擁堵情況下 紅色顯示
return Color.parseColor("#F41A25");
} else if (status.equals("嚴重擁堵")) { // 嚴重擁堵 豬肝紅顯示
return Color.parseColor("#AB1717");
} else { // 未知情況下藍色顯示
return Color.parseColor("#1590FF");
}
}
private int getcolorRes(String status) {
if (status.equals("暢通")) { // 暢通情況下 綠色顯示
return R.drawable.map_line_info_green;
} else if (status.equals("緩行")) { // 緩行情況下 黃色顯示
return R.drawable.map_line_info_yellow;
} else if (status.equals("擁堵")) { // 擁堵情況下 紅色顯示
return R.drawable.map_line_info_red;
} else if (status.equals("嚴重擁堵")) { // 嚴重擁堵 豬肝紅顯示
return R.drawable.map_line_info_red_more;
} else { // 未知情況下藍色顯示
return R.drawable.map_line_no_info_blue;
}
}
protected int getDriveColorRes() { // 暢通情況下 綠色顯示 TODO 可能會換成藍色
return R.drawable.map_line_info_green;
}
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();
}
}
private void addThroughPointMarker() {
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) {
throughPointMarkerList.add(mAMap
.addMarker((new MarkerOptions())
.position(
new LatLng(latLonPoint
.getLatitude(), latLonPoint
.getLongitude()))
.visible(throughPointMarkerVisible)
.icon(getThroughPointBitDes())
.title("\u9014\u7ECF\u70B9")));
}
}
}
}
private BitmapDescriptor getThroughPointBitDes() {
return BitmapDescriptorFactory.fromResource(R.drawable.amap_through);
}
/**
* 獲取兩點間距離
*
* @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();
}
}
}
高德地圖小知識,共勉