Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Dibujo de formas en Android MapView independientemente del nivel de zoom

Necesito dibujar formas iguales a las que crearías con mapas personalizados en Google Maps, usando MapView de Android.

En otras palabras, si dibujo una forma en el mapa, al alejar la imagen, debería reducirse, cubriendo la misma área del mapa independientemente del nivel de zoom.

Ejemplo de la referencia de 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; } 

Esto muestra un círculo blanco en el mapa, pero si se aleja, el círculo es del mismo tamaño. Tal vez el uso de lienzo no es el enfoque correcto?

Necesito algo parecido a cómo Google Maps destaca los barrios o ciudades:

Google Map que muestra los resultados de la búsqueda para Lower East Side, Nueva York

¿Algunas ideas? ¡Gracias por adelantado!

  • ¿Cómo abrir Google Maps con la dirección?
  • Android - Google Maps API v2 - NoClassDefFoundError
  • Definir ubicación Centro de mapa - GMaps v2 - Android
  • ¿Cómo puedo superponer modelo 3D en mapas de google o iOS?
  • ¿Hay algún límite para dibujar la ruta usando Geocoder (Android)?
  • Cómo obtener el evento de clic del texto del marcador
  • Añadir Google Maps API v2 en Mono para Android
  • Mapas fuera de línea SDK para Android e iOS
  • 4 Solutions collect form web for “Dibujo de formas en Android MapView independientemente del nivel de zoom”

    Tuve el mismo problema yo mismo, he aquí una solución completa con ubicaciones de demostración:

     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, eg 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; } } } 

    El radio de drawCircle es en píxeles por lo que tiene sentido que el círculo es siempre del mismo tamaño. Tiene que escalar el radio en función del nivel de zoom. El ejemplo siguiente graficará una geometría de la suite de topología JTS que se escalará.

     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) (cy * 1E6), (int) (cx * 1E6)), p); // Set path starting point to first coordinate // otherwise default start is (0,0) if (first) { mPath.moveTo(px, py); first = false; } // Add new point to path mPath.lineTo(px, py); } } // Draw the path with give paint canvas.drawPath(mPath, mPaint); } 

    Adaptado desde aquí: MapSelectionOverlay.java

    Esto quizás lo que usted está buscando: ¿Puede "superpuesta" el tamaño de zoom con el mapa de google en 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)))); } } 

    Lo que necesita es una lista de puntos lat / lon para cada forma que desee dibujar en el mapa. En el método onDraw, necesitas iterar sobre esa lista (para cada forma que quieras dibujar) y haz esto:

     //---translate the GeoPoint to screen pixels--- Point screenPts = new Point(); mapView.getProjection().toPixels(p, screenPts); 

    Luego dibuje la forma en el lienzo. IIRC que funciona correctamente independientemente del zoom, porque el mapView es consciente del nivel de zoom y le proporciona la ubicación de píxeles apropiada para el par lat / long en ese nivel de zoom.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.