您无需事先知道有多少种形状。如果您使用单独的叠加层,您可以轻松地绘制每个叠加层并将相应的区域添加到剪切区域。
完整代码如下:
import java.util.List;
import android.graphics.*;
import android.graphics.Path.Direction;
import android.graphics.Region.Op;
import android.os.Bundle;
import android.view.MotionEvent;
import com.google.android.maps.*;
public class CircleTest 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();
// m_map.getOverlays().add(new ); // some other overlays
m_map.getOverlays().add(new ImpactGeneratorOverlay());
// the impact areas are being inserted between these two, see ImpactGeneratorOverlay
m_map.getOverlays().add(new ImpactClipRestoreOverlay());
}
/**
* Restore clipping area to the saved one.
*/
public static class ImpactClipRestoreOverlay extends Overlay {
@Override
public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) {
super.draw(canvas, mapView, shadow);
canvas.restore();
}
}
/**
* Handles events, on touch down it adds a new Impact area to the map,
* just before the ClipRestore overlay (assume it's the last, if not store position, and insert before).
*/
public static class ImpactGeneratorOverlay extends Overlay {
@Override
public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) {
super.draw(canvas, mapView, shadow);
canvas.save();
}
@Override
public boolean onTouchEvent(final MotionEvent e, final MapView mapView) {
switch (e.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
GeoPoint point = mapView.getProjection().fromPixels((int) e.getX(), (int) e.getY());
List<Overlay> overlays = mapView.getOverlays();
overlays.add(overlays.size() - 1, new ImpactOverlay(point, 1000));
break;
}
return super.onTouchEvent(e, mapView);
}
}
/**
* Draw impact and remove the current shape path from the drawable area.
*/
public static class ImpactOverlay extends Overlay {
// shape parameters
private final GeoPoint circleCenter;
private final int circleRadius;
// drawing cache
private final Point circleDrawCenter = new Point();
private final Paint circlePaint = new Paint();
public ImpactOverlay(final GeoPoint circleCenter, final int circleRadius) {
this.circleCenter = circleCenter;
this.circleRadius = circleRadius;
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.argb(64, 255, 0, 0));
}
@Override
public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) {
// Transfrom geoposition to Point on canvas
Projection projection = mapView.getProjection();
projection.toPixels(circleCenter, circleDrawCenter);
// the circle to mark the spot
float circleDrawRadius = ImpactOverlay.metersToRadius(mapView, circleRadius, circleCenter.getLatitudeE6() / 1e6f);
// create circle from path
Path path = new Path();
path.addCircle(circleDrawCenter.x, circleDrawCenter.y, circleDrawRadius, Direction.CW);
// draw circle
canvas.drawPath(path, circlePaint);
// remove circle from further posibble drawing areas
canvas.clipPath(path, Op.DIFFERENCE);
}
public static float metersToRadius(final MapView map, final float meters, final float latitude) {
return (float) (map.getProjection().metersToEquatorPixels(meters) * (1 / Math.cos(Math.toRadians(latitude))));
}
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
}
这包含一个用于剪裁不需要的图层的修复程序,比如第一个,但是如果您只是将所有圆圈收集在一个叠加层中并在一个绘制方法中绘制它们,则可以避免这种情况。
关键是绘制和设置剪辑(即使它们存在于不同的叠加层中,也不建议!):
canvas.save();
canvas.drawPath(path1, paint);
canvas.clipPath(path1, Op.DIFFERENCE);
canvas.drawPath(path2, paint); // do not draw over path1
canvas.clipPath(path2, Op.DIFFERENCE);
canvas.drawPath(path3, paint); // do not draw over path1 + path2
canvas.clipPath(path3, Op.DIFFERENCE);
// do not draw over path1 + path2 + path3
canvas.restore();
canvas.drawPath(path4, paint); // draw over anything