Вам не нужно заранее знать, сколько там фигур.Если вы используете отдельные наложения, вы можете просто нарисовать каждый из них и добавить соответствующую область в область отсечения.
Полный код выглядит следующим образом:
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