在Android MapView上画一个圆形

17

问题已解决,以下是我的解决方案:

编辑:根据 robguinness 的回答进行了更新。

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;

public class CircleOverlay extends Overlay {

Context context;
double mLat;
double mLon;
float mRadius;

public CircleOverlay(Context _context, double _lat, double _lon, float radius ) {
    context = _context;
    mLat = _lat;
    mLon = _lon;
    mRadius = radius;
}

public CircleOverlay(Context _context, double _lat, double _lon, float radius ) {
    context = _context;
    mLat = _lat;
    mLon = _lon;
    mRadius = radius;
}

public void draw(Canvas canvas, MapView mapView, boolean shadow) {
    super.draw(canvas, mapView, shadow); 

    if(shadow) return; // Ignore the shadow layer

    Projection projection = mapView.getProjection();

    Point pt = new Point();

    GeoPoint geo = new GeoPoint((int) (mLat *1e6), (int)(mLon * 1e6));

    projection.toPixels(geo ,pt);
    float circleRadius = projection.metersToEquatorPixels(mRadius) * (1/ FloatMath.cos((float) Math.toRadians(mLat)));

    Paint innerCirclePaint;

    innerCirclePaint = new Paint();
    innerCirclePaint.setColor(Color.BLUE);
    innerCirclePaint.setAlpha(25);
    innerCirclePaint.setAntiAlias(true);

    innerCirclePaint.setStyle(Paint.Style.FILL);

    canvas.drawCircle((float)pt.x, (float)pt.y, circleRadius, innerCirclePaint);
}

}

若要进行“绘制”,需将其添加到地图叠加层中。

mMapView.getOverlays().add(new CircleOverlay(context, loc.getLatitude(),loc.getLongitude()));
希望这可以帮到你。

谢谢...我该如何改变圆的不透明度-透明度? - user836026
请查看此库以在地图上绘制圆形 v2:https://github.com/i-schuetz/map_areas - User
3个回答

8

被接受的答案存在错误。我试图进行更正,但我的编辑由于某种奇怪的原因被拒绝了。无论如何,这里是一个更正后的答案:

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;

public class CircleOverlay extends Overlay {

    Context context;
    double mLat;
    double mLon;
    float mRadius;

    public CircleOverlay(Context _context, double _lat, double _lon, float radius ) {
        context = _context;
        mLat = _lat;
        mLon = _lon;
        mRadius = radius;
    }

    public CircleOverlay(Context _context, double _lat, double _lon, float radius ) {
        context = _context;
        mLat = _lat;
        mLon = _lon;
        mRadius = radius;
    }

    public void draw(Canvas canvas, MapView mapView, boolean shadow) {
        super.draw(canvas, mapView, shadow); 

        if(shadow) return; // Ignore the shadow layer

        Projection projection = mapView.getProjection();

        Point pt = new Point();

        GeoPoint geo = new GeoPoint((int) (mLat *1e6), (int)(mLon * 1e6));

        projection.toPixels(geo ,pt);
        float circleRadius = projection.metersToEquatorPixels(mRadius) * (1/ FloatMath.cos((float) Math.toRadians(mLat)));

        Paint innerCirclePaint;

        innerCirclePaint = new Paint();
        innerCirclePaint.setColor(Color.BLUE);
        innerCirclePaint.setAlpha(25);
        innerCirclePaint.setAntiAlias(true);

        innerCirclePaint.setStyle(Paint.Style.FILL);

        canvas.drawCircle((float)pt.x, (float)pt.y, circleRadius, innerCirclePaint);
    }
}

在 Scott 的答案中存在的问题是,circleRadius 的计算是使用一种将赤道上的点从米转换为像素的方法。然而,如果您所需的点不在赤道上,则半径会太小,因为该转换未考虑经线在极点处汇合的事实。然而,可以通过乘以 (1/ FloatMath.cos((float) Math.toRadians(mLat))) 进行更正,这是我对 Scott 原始答案唯一的更改。
希望这能帮助某些人,因为我是通过艰难的方式发现了这个问题。我住在芬兰,在使用原始方法时,圆圈大小比应该小了约两倍!

7

我已经将上述示例进行了扩展,以考虑需要根据地图缩放级别(即:相对于地面距离)缩放的圆形。

有些人可能会发现这很有用。

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;

public class CircleOverlay extends Overlay {

    Context context;
    double mLat;
    double mLon;
    float mRadius;

     public CircleOverlay(Context _context, double _lat, double _lon, float radius ) {
            context = _context;
            mLat = _lat;
            mLon = _lon;
            mRadius = radius;
     }

     public void draw(Canvas canvas, MapView mapView, boolean shadow) {
         super.draw(canvas, mapView, shadow); 

         if(shadow) return; // Ignore the shadow layer

         Projection projection = mapView.getProjection();

         Point pt = new Point();

         GeoPoint geo = new GeoPoint((int) (mLat *1e6), (int)(mLon * 1e6));

         projection.toPixels(geo ,pt);
         float circleRadius = projection.metersToEquatorPixels(mRadius) * (1/ FloatMath.cos((float) Math.toRadians(mLat)));

         Paint innerCirclePaint;

         innerCirclePaint = new Paint();
         innerCirclePaint.setColor(Color.BLUE);
         innerCirclePaint.setAlpha(25);
         innerCirclePaint.setAntiAlias(true);

         innerCirclePaint.setStyle(Paint.Style.FILL);

         canvas.drawCircle((float)pt.x, (float)pt.y, circleRadius, innerCirclePaint);
    }
}

我发现这个答案很有用,但最终发现了一个错误。我试图编辑它,但最终不得不发布一个单独的答案,因为我的编辑被拒绝了(仍然不明白为什么…)。 - robguinness
是的,我认为审核者有点吹毛求疵了。无论如何,我已经添加了你建议的编辑。;-) - Scott

0
  1. 您要显示的地理坐标点是(0.1275,51.507222)吗?这个坐标位于索马里海岸附近。

  2. super.draw(..) 应该是您的 draw() 方法中的第一条语句。


我已经意识到第一个点了 =P,现在我将执行第二个点,但是我如何获取主类使用的画布的引用呢? - nhunston

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接