这是我开发的一个工作示例,使用与 Doug 建议的相同概念,采用 JavaScript 示例 (http://econym.org.uk/gmap/example_arrows.htm) 并将其转换为 Java 代码。为了方便起见,它使用来自谷歌地图服务器的图像,但这些图像可能是您设计的图像,也可能是从网络上抓取并存储在本地应用程序中。我在主线程上下载这些是为了演示,但如果在实时应用中使用,请不要这样做!
与 JavaScript 示例的主要区别在于,您必须将箭头图像投影到大小为四倍的较大图像上,根据从 A 到 B 的方位计算出将图像转换到的位置,最后居中通过为图标添加另一个带有较大图像的锚定标记,将该图像覆盖在现有 B 标记上。
首先添加你的折线:
PolylineOptions polylines = new PolylineOptions();
LatLng from = new LatLng(f.getLatitude(), f.getLongitude());
LatLng to = new LatLng(t.getLatitude(), t.getLongitude());
polylines.add(from, to).color(polyColor).width(2);
mMap.addPolyline(polylines);
DrawArrowHead(mMap, from, to);
然后添加你的箭头:
private final double degreesPerRadian = 180.0 / Math.PI;
private void DrawArrowHead(GoogleMap mMap, LatLng from, LatLng to){
// obtain the bearing between the last two points
double bearing = GetBearing(from, to);
// round it to a multiple of 3 and cast out 120s
double adjBearing = Math.round(bearing / 3) * 3;
while (adjBearing >= 120) {
adjBearing -= 120;
}
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
// Get the corresponding triangle marker from Google
URL url;
Bitmap image = null;
try {
url = new URL("http://www.google.com/intl/en_ALL/mapfiles/dir_" + String.valueOf((int)adjBearing) + ".png");
try {
image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (image != null){
// Anchor is ratio in range [0..1] so value of 0.5 on x and y will center the marker image on the lat/long
float anchorX = 0.5f;
float anchorY = 0.5f;
int offsetX = 0;
int offsetY = 0;
// images are 24px x 24px
// so transformed image will be 48px x 48px
//315 range -- 22.5 either side of 315
if (bearing >= 292.5 && bearing < 335.5){
offsetX = 24;
offsetY = 24;
}
//270 range
else if (bearing >= 247.5 && bearing < 292.5){
offsetX = 24;
offsetY = 12;
}
//225 range
else if (bearing >= 202.5 && bearing < 247.5){
offsetX = 24;
offsetY = 0;
}
//180 range
else if (bearing >= 157.5 && bearing < 202.5){
offsetX = 12;
offsetY = 0;
}
//135 range
else if (bearing >= 112.5 && bearing < 157.5){
offsetX = 0;
offsetY = 0;
}
//90 range
else if (bearing >= 67.5 && bearing < 112.5){
offsetX = 0;
offsetY = 12;
}
//45 range
else if (bearing >= 22.5 && bearing < 67.5){
offsetX = 0;
offsetY = 24;
}
//0 range - 335.5 - 22.5
else {
offsetX = 12;
offsetY = 24;
}
Bitmap wideBmp;
Canvas wideBmpCanvas;
Rect src, dest;
// Create larger bitmap 4 times the size of arrow head image
wideBmp = Bitmap.createBitmap(image.getWidth() * 2, image.getHeight() * 2, image.getConfig());
wideBmpCanvas = new Canvas(wideBmp);
src = new Rect(0, 0, image.getWidth(), image.getHeight());
dest = new Rect(src);
dest.offset(offsetX, offsetY);
wideBmpCanvas.drawBitmap(image, src, dest, null);
mMap.addMarker(new MarkerOptions()
.position(to)
.icon(BitmapDescriptorFactory.fromBitmap(wideBmp))
.anchor(anchorX, anchorY));
}
}
private double GetBearing(LatLng from, LatLng to){
double lat1 = from.latitude * Math.PI / 180.0;
double lon1 = from.longitude * Math.PI / 180.0;
double lat2 = to.latitude * Math.PI / 180.0;
double lon2 = to.longitude * Math.PI / 180.0;
// Compute the angle.
double angle = - Math.atan2( Math.sin( lon1 - lon2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lon1 - lon2 ) );
if (angle < 0.0)
angle += Math.PI * 2.0;
// And convert result to degrees.
angle = angle * degreesPerRadian;
return angle;
}