我需要使用Android的MapView在Google地图上使用自定义地图创建形状。
换句话说,如果我在地图上绘制一个形状,当我缩小它时它应该缩小,覆盖地图的相同区域而不管缩放级别。
Android参考后面的示例:
@Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when)
{
super.draw(canvas, mapView, shadow);
//---translate the GeoPoint to screen pixels---
Point screenPts = new Point();
mapView.getProjection().toPixels(p, screenPts);
Paint boxPaint = new Paint();
boxPaint.setColor(android.graphics.Color.WHITE);
boxPaint.setStyle(Paint.Style.FILL);
boxPaint.setAlpha(140);
canvas.drawCircle(screenPts.x, screenPts.y, 20, boxPaint);
return true;
}
这会在地图上显示一个白色圆圈,但如果缩小,则圆圈大小相同。也许使用canvas是不正确的方法?
我需要谷歌地图如何突出社区或城市:
有什么想法吗?提前谢谢!
答案 0 :(得分:8)
我自己也有同样的问题,这里是一个带有演示位置的完整解决方案:
import java.util.*;
import android.graphics.*;
import android.graphics.Paint.Style;
import android.graphics.Region.Op;
import android.os.Bundle;
import com.google.android.maps.*;
public class ShapeOverlayTest extends MapActivity {
private MapView m_map;
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
m_map = (MapView) findViewById(R.id.mapview);
m_map.displayZoomControls(true);
m_map.setBuiltInZoomControls(true);
}
@Override
protected void onStart() {
super.onStart();
Loc[][] areas = {
{
new Loc(51.51695436113811, -0.28686325139653757),
new Loc(51.5268179962453, -0.28118722558738923),
new Loc(51.526498459594215, -0.27779666308279755),
new Loc(51.52521530775356, -0.26943974607777654),
new Loc(51.52292555645698, -0.25813738590178786),
new Loc(51.52054465991048, -0.2498381618983569),
new Loc(51.51012230470141, -0.24509233633017083),
new Loc(51.50884762913046, -0.24465130560570497),
new Loc(51.50732063336974, -0.2441767643132881),
new Loc(51.50431624597833, -0.24473900326760137),
new Loc(51.49756328092904, -0.2714528238165076),
new Loc(51.50092541797557, -0.28360267232347336),
new Loc(51.50205958485736, -0.28490018935582045),
new Loc(51.50488447379555, -0.28681164237730944)
},
{
new Loc(51.50368617913765, -0.25313579464343156),
new Loc(51.51978611305675, -0.24842567405905958),
new Loc(51.51039382684418, -0.24460628015366626),
new Loc(51.508792552597576, -0.24397604687682156),
new Loc(51.50713008309719, -0.24346350415674722),
new Loc(51.502411013302684, -0.2508501075008919),
new Loc(51.502377240039664, -0.25160073203846817),
new Loc(51.50274364303565, -0.25204783703705536)
},
{
new Loc(51.49924084955314, -0.2858705706471945),
new Loc(51.50212820259818, -0.2791479893522646),
new Loc(51.49724510427319, -0.27427453152961206),
new Loc(51.49429724502515, -0.2799184038304611),
new Loc(51.494270969987404, -0.28180678948730314)
}
};
String[] areaNames = { "W3 Ealing", "W3 Hammersmith & Fulham", "W3 Hounslow" };
// for (Map.Entry<String, List<Loc>> area : m_areas.entrySet()) {
// // to have much less points and make sure they are in order
// // the demo data already has these properties
// // http://en.wikipedia.org/wiki/Gift_wrapping_algorithm#Pseudocode
// area.setValue(Algo.convexHull(area.getValue()));
// }
Map<String, List<GeoPoint>> areaMap = new HashMap<String, List<GeoPoint>>();
for (int i = 0; i < areaNames.length; i++) {
List<GeoPoint> points = new ArrayList<GeoPoint>();
for (int j = 0; j < areas[i].length; j++) {
points.add(areas[i][j].toGeoPoint());
}
areaMap.put(areaNames[i], points);
}
m_map.getOverlays().add(new AreasOverlay(areaMap));
// TODO determine location better, e.g. averaging area points
GeoPoint center = new GeoPoint(51509704, -270710);
m_map.getController().setCenter(center);
m_map.getController().setZoom(15);
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
static class Loc {
private double m_lat;
private double m_lon;
public Loc(final double lat, final double lon) {
m_lat = lat;
m_lon = lon;
}
public GeoPoint toGeoPoint() {
return new GeoPoint((int) (m_lat * 1e6), (int) (m_lon * 1e6));
}
};
static class AreasOverlay extends Overlay {
private final Map<String, List<GeoPoint>> m_areas;
private final Paint m_paintFill;
private final Paint m_paintStroke;
private static final int ALPHA = 0x30ffffff; // 48 out of 255 transparent
private static final int[] COLORS =
{ Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.GREEN, Color.BLUE };
static {
for (int i = 0; i < AreasOverlay.COLORS.length; i++) {
AreasOverlay.COLORS[i] &= AreasOverlay.ALPHA;
}
}
public AreasOverlay(final Map<String, List<GeoPoint>> areaMap) {
m_areas = areaMap;
// prepare paints
m_paintFill = new Paint();
m_paintFill.setStyle(Paint.Style.FILL);
m_paintStroke = new Paint(Paint.ANTI_ALIAS_FLAG);
m_paintStroke.setStyle(Style.STROKE);
m_paintStroke.setAntiAlias(true);
m_paintStroke.setStrokeWidth(3);
}
@Override
public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) {
super.draw(canvas, mapView, shadow);
if (shadow) {
return;
}
Projection projection = mapView.getProjection();
List<Path> areaPaths = getPaths(projection, m_areas);
drawPaths(canvas, areaPaths);
}
private List<Path> getPaths(final Projection projection, final Map<String, List<GeoPoint>> areas) {
List<Path> areaPaths = new ArrayList<Path>(areas.size());
for (Map.Entry<String, List<GeoPoint>> entry : areas.entrySet()) {
List<GeoPoint> sourceList = entry.getValue();
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
Iterator<GeoPoint> it = sourceList.iterator();
Point point = nextDrawPoint(projection, it);
path.moveTo(point.x, point.y);
while (it.hasNext()) {
point = nextDrawPoint(projection, it);
path.lineTo(point.x, point.y);
}
path.close();
areaPaths.add(path);
}
return areaPaths;
}
/**
* <ul>
* <li>Draw with different colors.
* <li>Draw strokes first for them to be always visible.
* <li>Draw fills next with each removing from the drawable area.
* </ul>
*/
private void drawPaths(final Canvas canvas, final List<Path> areaPaths) {
int currentColorIndex;
currentColorIndex = 0;
for (Path path : areaPaths) {
int currentColor = AreasOverlay.COLORS[currentColorIndex++];
currentColorIndex %= AreasOverlay.COLORS.length;
m_paintStroke.setColor(currentColor & 0xff7f7f7f); // make it darker by clearing the high bit
canvas.drawPath(path, m_paintStroke);
}
currentColorIndex = 0;
for (Path path : areaPaths) {
int currentColor = AreasOverlay.COLORS[currentColorIndex++];
currentColorIndex %= AreasOverlay.COLORS.length;
m_paintFill.setColor(currentColor);
canvas.drawPath(path, m_paintFill);
canvas.clipPath(path, Op.DIFFERENCE); // don't allow to draw over each other
}
}
private Point nextDrawPoint(final Projection projection, final Iterator<GeoPoint> it) {
GeoPoint geo = it.next();
Point p = new Point();
projection.toPixels(geo, p);
return p;
}
}
}
答案 1 :(得分:5)
drawCircle的半径以像素为单位,因此圆圈的大小始终相同。您必须根据缩放级别缩放半径。下面的示例将绘制将扩展的JTS拓扑套件中的几何图形。
public class MapOverlay extends Overlay {
private static final String TAG = MapOverlay.class.getName();
// Allocate once and reuse
private final Paint mPaint = new Paint();
private final Path mPath = new Path();
// Region to highlight
private Geometry mGeometry;
/**
* @param geometry Region to highlight on map
*/
public MapOverlay(Geometry geometry) {
// Set region
mGeometry = geometry;
// Edit paint style
mPaint.setDither(true);
mPaint.setColor(Color.rgb(128, 136, 231));
mPaint.setAlpha(100);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(6);
}
/**
* Draw the overlay over the map.
*
* @see com.google.android.maps.Overlay#draw(Canvas, MapView, boolean)
*/
@Override
public void draw(Canvas canvas, MapView mapv, boolean shadow) {
super.draw(canvas, mapv, shadow);
if (mGeometry != null) {
// TODO There could be more than one geometries
Geometry g = mGeometry.getGeometryN(0);
final Point p = new Point();
boolean first = true;
mPath.reset();
for (Coordinate c : g.getCoordinates()) {
// Convert lat/lon to pixels on screen
// GeoPoint is immutable so allocation is unavoidable
Projection projection = mapv.getProjection();
projection.toPixels(new GeoPoint((int) (c.y * 1E6), (int) (c.x * 1E6)), p);
// Set path starting point to first coordinate
// otherwise default start is (0,0)
if (first) {
mPath.moveTo(p.x, p.y);
first = false;
}
// Add new point to path
mPath.lineTo(p.x, p.y);
}
}
// Draw the path with give paint
canvas.drawPath(mPath, mPaint);
}
改编自此处:MapSelectionOverlay.java
答案 2 :(得分:2)
这可能是您正在寻找的内容:Can "overlay" size be zoomed together with the google map on android?
public class ImpactOverlay extends Overlay {
private static int CIRCLERADIUS = 0;
private GeoPoint geopoint;
public ImpactOverlay(GeoPoint point, int myRadius) {
geopoint = point;
CIRCLERADIUS = myRadius;
}
@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
// Transfrom geoposition to Point on canvas
Projection projection = mapView.getProjection();
Point point = new Point();
projection.toPixels(geopoint, point);
// the circle to mark the spot
Paint circle = new Paint();
circle.setColor(Color.BLACK);
int myCircleRadius = metersToRadius(CIRCLERADIUS, mapView, (double)geopoint.getLatitudeE6()/1000000);
canvas.drawCircle(point.x, point.y, myCircleRadius, circle);
}
public static int metersToRadius(float meters, MapView map, double latitude) {
return (int) (map.getProjection().metersToEquatorPixels(meters) * (1/ Math.cos(Math.toRadians(latitude))));
}
}
答案 3 :(得分:2)
您需要的是要在地图上绘制的每个形状的纬度/经度点列表。在onDraw方法中,您需要迭代该列表(对于您要绘制的每个形状),并执行以下操作:
//---translate the GeoPoint to screen pixels---
Point screenPts = new Point();
mapView.getProjection().toPixels(p, screenPts);
然后在画布上绘制形状。无论缩放如何,IIRC都能正常工作,因为mapView知道缩放级别,并为该缩放级别的纬度/经度对提供合适的像素位置。