Android card circular overlay, dynamically change the radius?

I have a MapView in my application and draw some circular labels on this map. Everything works fine, but when I zoom in on the map, the blending radius does not change. I tried to find forums and google for a solution, but could not find the one that worked for me. Does anyone have any ideas?

Here is my code:

HelloGoogleMaps.java (main action)

package com.adam.maps; import java.util.Iterator; import java.util.List; import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.AbsoluteLayout; import android.widget.RelativeLayout; import android.widget.Toast; import android.widget.ZoomButtonsController.OnZoomListener; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; public class HelloGoogleMaps extends MapActivity { //create new LocationManager //and LocationListener objects LocationManager lm; LocationListener locationListener; OnZoomListener listener; //create a new MapView //and MapController object MapView mapView; MapController mc; RelativeLayout parent; int num = 4; //LoopRegion region[] = new LoopRegion[num]; //LoopRegion border[] = new LoopRegion[num]; float regionX[] = {(float) 42.91556645193364, (float) 42.9151598328247, (float) 43.00110298764482, (float) 43.00054196511636}; float regionY[] = {(float) -78.87073255078127, (float) -78.8714594294243, (float) -78.78354466454317, (float) -78.78226256863405}; int regionR[] = {100, 70, 150, 75}; GeoPoint regionC[] = new GeoPoint[num]; CustomOverlay overlay[] = new CustomOverlay[num]; CustomOverlay overlayLoc; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Toast.makeText(getBaseContext(), "Welcome to 'sound clusters'" , Toast.LENGTH_LONG).show(); //---use the LocationManager class to obtain GPS locations--- lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); locationListener = new MyLocationListener(); lm.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, locationListener); //set our mapViewer object to our "mapview" namespace in the xml layout file //this allows us to set the zoom control "ON" in our view mapView = (MapView) findViewById(R.id.mapview); //this will enable zoom controls, and put it on the screen mapView.setBuiltInZoomControls(true); //--------------------------------------------------------// parent = (RelativeLayout) findViewById(R.id.parent); //-------this is part of creating an overlay icon------------------------------- /*List<Overlay> mapOverlays = mapView.getOverlays(); Drawable drawable = this.getResources().getDrawable(R.drawable.icon); CustomItemizedOverlay itemizedOverlay = new CustomItemizedOverlay(drawable, this);*/ //------------------------------------------------------------------------------ // Create new Overlay for (int i = 0; i < num; i++){ regionC[i] = new GeoPoint( (int) (regionX[i] * 1E6), (int) (regionY[i] * 1E6)); int newRadius = (int) feetToPixels(mapView.getZoomLevel(), regionR[i]); overlay[i] = new CustomOverlay(regionC[i], newRadius); mapView.getOverlays().add(overlay[i]); } //-------this is part of creating an overlay icon------------------------------- /*OverlayItem overlayitem = new OverlayItem(point, "Hello", "I'm in Athens, Greece!"); itemizedOverlay.addOverlay(overlayitem); mapOverlays.add(itemizedOverlay);*/ //------------------------------------------------------------------------------ mc = mapView.getController(); mc.setZoom(20); mapView.setSatellite(true); Toast.makeText(getBaseContext(), "Zoom level: " + mapView.getZoomLevel(), Toast.LENGTH_SHORT).show(); } //not sure what this does, but Google says you need it----// @Override protected boolean isRouteDisplayed() { return false; } //--------------------------------------------------------// private class MyLocationListener implements LocationListener { //@Override public void onLocationChanged(Location loc) { if (loc != null) { List overlays = mapView.getOverlays(); // first remove old overlay if (overlays.size() > 0) { for (Iterator iterator = overlays.iterator(); iterator .hasNext();) { iterator.next(); iterator.remove(); } } GeoPoint p = new GeoPoint( (int) (loc.getLatitude() * 1E6), (int) (loc.getLongitude() * 1E6)); overlayLoc = new CustomOverlay(p, 5); mapView.getOverlays().add(overlayLoc); for (int i = 0; i < num; i++){ mapView.getOverlays().add(overlay[i]); } //mc.animateTo(p); //mc.setZoom(16); mapView.invalidate(); } } //@Override public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } //@Override public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } //@Override public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } } //custom functions-------------------------------------------------------------------- private static final double equatorFeet = 131479920; private double feetToPixels(int zoomLevel, int feet) { double equatorPixels = 256; for (int i = 1; i < zoomLevel; i++) { equatorPixels = equatorPixels * 2; } double pixelPerFoot = equatorPixels / equatorFeet; return feet * pixelPerFoot; } //------------------------------------------------------------------------------------ } 

And the class Overlay CustomOverlay.java

 package com.adam.maps; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Point; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapView; import com.google.android.maps.Overlay; import com.google.android.maps.Projection; public class CustomOverlay extends Overlay { private GeoPoint geopoint; private int rad; public CustomOverlay(GeoPoint point, int radius) { geopoint = point; rad = radius; } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { // Transform geo-position to Point on canvas Projection projection = mapView.getProjection(); Point point = new Point(); //store the transformed geopoint into a point with pixel values projection.toPixels(geopoint, point); /*// text "My Location" Paint text = new Paint(); text.setAntiAlias(true); text.setColor(Color.BLUE); text.setTextSize(12); text.setTypeface(Typeface.MONOSPACE);*/ // the circle to mark the spot Paint circlePaint = new Paint(); circlePaint.setAntiAlias(true); //fill region circlePaint.setColor(Color.RED); circlePaint.setAlpha(90); circlePaint.setStyle(Paint.Style.FILL); canvas.drawCircle(point.x, point.y, rad, circlePaint); //border region circlePaint.setColor(Color.WHITE); circlePaint.setAlpha(255); circlePaint.setStyle(Paint.Style.STROKE); circlePaint.setStrokeWidth(3); canvas.drawCircle(point.x, point.y, rad, circlePaint); /*canvas.drawText("My Location", point.x + 3 * CIRCLERADIUS, point.y + 3 * CIRCLERADIUS, text);*/ } } 

Thank you in advance for your help!

+4
source share
5 answers

I know this topic a few months ago, but there are ALL simple ways to achieve very similar results. I understand that the method presented provides a much more accurate calculation of the size of the circle, but still, if you only need a circle around averaging a certain area, this code requires much less processing, making the user interface more fluid:

 public class MapCircleOverlay extends Overlay { private GeoPoint point; private Paint paint1, paint2; public MapCircleOverlay(GeoPoint point) { this.point = point; paint1 = new Paint(); paint1.setARGB(128, 0, 0, 255); paint1.setStrokeWidth(2); paint1.setStrokeCap(Paint.Cap.ROUND); paint1.setAntiAlias(true); paint1.setDither(false); paint1.setStyle(Paint.Style.STROKE); paint2 = new Paint(); paint2.setARGB(64, 0, 0, 255); } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { Point pt = mapView.getProjection().toPixels(point, null); float radius = (float) Math.pow(2, mapView.getZoomLevel() - 10); if(radius < canvas.getHeight()/25){ radius = canvas.getHeight()/25; } canvas.drawCircle(pt.x, pt.y, radius, paint2); canvas.drawCircle(pt.x, pt.y, radius, paint1); } } 

Explanation: the documentation indicates that for each scaling value, the map doubles (or half) the size, so that while the radius doubles or halves, its size will be consistent with the figures.

"-10" can be changed to resize the circle (possibly in the constructor, if desired)

Also, the calculation of min_r (minimum radius) can be changed as desired, it is only there to prevent the complete disappearance of the circle with increasing user size.

hope this helps someone;)

+3
source
 import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapView; import com.google.android.maps.Overlay; public class MapCircleOverlay extends Overlay { private GeoPoint point; private Paint paint1, paint2; private float radius; //in meters public MapCircleOverlay(GeoPoint point, float radius) { this.point = point; paint1 = new Paint(); paint1.setARGB(128, 0, 0, 255); paint1.setStrokeWidth(2); paint1.setStrokeCap(Paint.Cap.ROUND); paint1.setAntiAlias(true); paint1.setDither(false); paint1.setStyle(Paint.Style.STROKE); paint2 = new Paint(); paint2.setARGB(64, 0, 0, 255); this.radius = radius; } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { Point pt = mapView.getProjection().toPixels(point, null); float projectedRadius = mapView.getProjection().metersToEquatorPixels(radius); canvas.drawCircle(pt.x, pt.y, projectedRadius, paint2); canvas.drawCircle(pt.x, pt.y, projectedRadius, paint1); } } 

I modified Bundius answer to work with meters that you can enter as part of the constructor.

+7
source
 class myLocationOverlay extends com.google.android.maps.Overlay { private static final double defaultLatitude = Double.parseDouble("your_default_latitude"); private static final double defaultLongitude = Double.parseDouble("your_default_longitude"); private static final float defaultAccuracy = 250f; // or whatever you wish it to be Location currentLocation; // this should be already known private Paint accuracyPaint; private Point center; private Point left; private Drawable drawable; private int width; private int height; @Override public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) { super.draw(canvas, mapView, shadow); accuracyPaint = new Paint(); accuracyPaint.setAntiAlias(true); accuracyPaint.setStrokeWidth(2.0f); drawable = mapView.getContext().getResources().getDrawable(R.drawable.my_location_dot); width = drawable.getIntrinsicWidth(); height = drawable.getIntrinsicHeight(); center = new Point(); left = new Point(); double latitude; double longitude; float accuracy; Projection projection = mapView.getProjection(); if(currentLocation == null) { latitude = defaultLatitude; longitude = defaultLongitude; accuracy = defaultAccuracy; } else { latitude = currentLocation.getLatitude(); longitude = currentLocation.getLongitude(); accuracy = currentLocation.getAccuracy(); } float[] result = new float[1]; Location.distanceBetween(latitude, longitude, latitude, longitude + 1, result); float longitudeLineDistance = result[0]; GeoPoint leftGeo = new GeoPoint((int)(latitude * 1E6), (int)((longitude - accuracy / longitudeLineDistance) * 1E6)); projection.toPixels(leftGeo, left); projection.toPixels(myLocationPoint, center); int radius = center.x - left.x; accuracyPaint.setColor(0xff6666ff); accuracyPaint.setStyle(Style.STROKE); canvas.drawCircle(center.x, center.y, radius, accuracyPaint); accuracyPaint.setColor(0x186666ff); accuracyPaint.setStyle(Style.FILL); canvas.drawCircle(center.x, center.y, radius, accuracyPaint); drawable.setBounds(center.x - width / 2, center.y - height / 2, center.x + width / 2, center.y + height / 2); drawable.draw(canvas); return true; } } 

Change R.drawable. my_location_dot on everything you use as a location marker and make sure currentLocation is known

+1
source

Sorry, I know that the accepted answer is old, but there is my own and best solution.

  // Add a circle in Sydney Circle circle = map.addCircle(new CircleOptions() .center(new LatLng(-33.87365, 151.20689)) .radius(10000) .strokeColor(Color.RED) .fillColor(Color.BLUE)); 

I hope this helps someone =)

Link: Here

+1
source
 private CircleOptions circle; double radiusInMeters = 50.0; int strokeColor = 0xffff0000; //red outline int shadeColor = 0x44ff0000; @Override public void onLocationChanged(Location location) { ... LatLng mylatlng= new LatLng(currentLat, currentLon); circle = new CircleOptions().center(mylatlng).radius(radiusInMeters).fillColor(shadeColor).strokeColor(strokeColor).strokeWidth(3); mMap.addCircle(circle); ... } 
+1
source

All Articles