我的应用中有一个MapView,并在此地图上绘制了几个圆形叠加层。一切都很好,但是当我放大地图时,叠加半径不会改变。我已经尝试搜索论坛和谷歌寻求解决方案,但找不到一个适合我的方案。有没有人有任何想法?
这是我的代码:
HelloGoogleMaps.java(主要活动)
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;
}
//------------------------------------------------------------------------------------
}
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);*/
}
}
提前感谢您的帮助!
答案 0 :(得分:7)
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);
}
}
我修改了Bundius的答案,因此它适用于您可以作为构造函数的一部分输入的米。
答案 1 :(得分:3)
我知道这个帖子已经有几个月了,但总有更简单的方法可以达到非常相似的效果。 据我所知,所提出的方法可以更精确地计算圆的大小,但是,如果你只需要平均一些区域的任何圆,这个代码需要更少的处理,使UI更流畅:
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);
}
}
说明: 文档指出,对于每个zoomLevel,地图将大小加倍(或减半),因此只要半径加倍或减半,其大小将在图纸之间保持一致。
可以更改“-10”以改变圆的大小(如果需要,可以在构造函数中完成)
此外,min_r(最小半径)计算可以根据需要进行调整,只是为了防止圆圈在用户缩小时完全消失。
希望它可以帮助某人;)
答案 2 :(得分:1)
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;
}
}
使用您用作位置标记的任何内容更改R.drawable。 my_location_dot ,并查看currentLocation是否已知
答案 3 :(得分:1)
对不起,我知道这个被接受的答案是旧的,但是存在一个原生的更好的解决方案。
// 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));
我希望这可以帮助某人=)
参考:Here
答案 4 :(得分:1)
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);
...
}