2016-03-02 104 views
1

我一直在研究在Google地图上绘制一个静态半径的圆,我遇到的所有答案都描述了绘制标记和与纬度坐标相关的圆圈。如何在Google地图上绘制静态目标圈?

我需要是这样的:

enter image description here

圈和浮标记上面的谷歌地图片段,即:当平移和缩放,它保持静态。这里是一个棘手的部分:我希望能够在地图上获得覆盖区域以便处理(例如:取决于地图上的缩放级别,纬度,中心标记的长度和圆的半径) 。

我该如何做到这一点?提前致谢。

+0

JavaScript API或Android API? – MrUpsidown

+0

我认为你所要求的有点复杂,如果你想获得覆盖区域的数据。 [此票](http://stackoverflow.com/questions/5722490/android-maps-circle-overlay-dynamically-change-radius)可能能够为您提供有关浮动圈(自定义叠加层)的解决方案。 – adjuremods

+0

@MrUpsidown AndroidAPI – TwiZtor

回答

4

您可以创建自定义View来绘制圆。我基于我的示例Draw transparent circle filled outside

Here您可以找到有关如何创建自定义视图的教程。

在我的示例中,我使用radius参数创建了自定义RadarOverlayView,该参数用于计算面积。

我的自定义视图的代码:

public class RadarOverlayView extends LinearLayout { 
    private Bitmap windowFrame; 
    private float radius = 0f; 
    private int centerX = 0; 
    private int centerY = 0; 

    public RadarOverlayView(Context context) { 
     super(context); 
    } 

    public RadarOverlayView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     TypedArray a = context.getTheme().obtainStyledAttributes(
       attrs, R.styleable.RadarOverlayView, 0, 0); 

     try { 
      radius = a.getDimension(R.styleable.RadarOverlayView_radius, 0f); 
     } finally { 
      a.recycle(); 
     } 
    } 

    @Override 
    protected void dispatchDraw(Canvas canvas) { 
     super.dispatchDraw(canvas); 

     if (windowFrame == null) { 
      createWindowFrame(); 
     } 
     canvas.drawBitmap(windowFrame, 0, 0, null); 
    } 

    @Override 
    public boolean isEnabled() { 
     return false; 
    } 

    @Override 
    public boolean isClickable() { 
     return false; 
    } 

    protected void createWindowFrame() { 
     windowFrame = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); 
     Canvas osCanvas = new Canvas(windowFrame); 

     centerX = getWidth()/2; 
     centerY = getHeight()/2; 

     if (radius > 0) { 
      Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 

      // Draw the circunference 
      paint.setStyle(Paint.Style.STROKE); 
      paint.setColor(Color.RED); 
      paint.setAlpha(200); 
      paint.setStrokeWidth(5); 
      osCanvas.drawCircle(centerX, centerY, radius, paint); 

      // Draw the circle 
      paint.setStyle(Paint.Style.FILL); 
      paint.setColor(Color.RED); 
      paint.setAlpha(100); 
      osCanvas.drawCircle(centerX, centerY, radius, paint); 

      // Draw the center icon 
      paint.setAlpha(255); 
      Bitmap centerBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); 
      osCanvas.drawBitmap(centerBitmap, centerX - centerBitmap.getWidth()/2, 
        centerY - centerBitmap.getHeight()/2, 
        paint); 
     } 
    } 

    @Override 
    public boolean isInEditMode() { 
     return true; 
    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 
     super.onLayout(changed, l, t, r, b); 
     windowFrame = null; 
    } 

    public float getRadius() { 
     return radius; 
    } 

    public int getCenterX() { 
     return centerX; 
    } 

    public int getCenterY() { 
     return centerY; 
    } 
} 

我attrs.xml:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <declare-styleable name="RadarOverlayView"> 
     <attr name="radius" format="dimension" /> 
    </declare-styleable> 
</resources> 

我activity_maps.xml布局:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       xmlns:tools="http://schemas.android.com/tools" 
       xmlns:app="http://schemas.android.com/apk/res-auto" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:orientation="vertical"> 
    <fragment 
     android:id="@+id/map" 
     android:name="myPackage.MySupportMapFragment" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     tools:context=".MapsActivity"/> 
    <myPackage.RadarOverlayView 
     android:id="@+id/radar" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_centerInParent="true" 
     app:radius="150dp" /> 
</RelativeLayout> 

我的活动:

public class MapsActivity extends FragmentActivity implements GoogleMap.OnCameraChangeListener { 
    private GoogleMap mMap; 
    private RadarOverlayView radarView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_maps); 
     radarView = (RadarOverlayView) findViewById(R.id.radar); 
     setUpMapIfNeeded(); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     setUpMapIfNeeded(); 
    } 

    private void setUpMapIfNeeded() { 
     if (mMap == null) { 
      mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)) 
        .getMap(); 
      if (mMap != null) { 
       setUpMap(); 
      } 
     } 
    } 

    private void setUpMap() { 
     mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); 
     mMap.getUiSettings().setAllGesturesEnabled(true); 
     mMap.getUiSettings().setZoomControlsEnabled(true); 

     mMap.setOnCameraChangeListener(this); 
    } 

    @Override 
    public void onCameraChange(final CameraPosition cameraPosition) { 
     // Compute the area of the circle each time the camera changes 

     LatLng center = mMap.getProjection().fromScreenLocation(
       new Point(radarView.getCenterX(), radarView.getCenterY())); 
     LatLng right = mMap.getProjection().fromScreenLocation(
       new Point(radarView.getCenterX() + Math.round(radarView.getRadius()), 
         radarView.getCenterY())); 

     Location locationCenter = new Location("center"); 
     locationCenter.setLatitude(center.latitude); 
     locationCenter.setLongitude(center.longitude); 

     Location locationRight = new Location("right"); 
     locationRight.setLatitude(right.latitude); 
     locationRight.setLongitude(right.longitude); 

     double geoRadius = locationCenter.distanceTo(locationRight); 
     double geoArea = Math.PI * Math.pow(geoRadius, 2); 

     // Uncomment to inspect the difference between 
     // RadarOverlayView circle and geographic circle: 
     // mMap.clear(); 
     // Circle circle = mMap.addCircle(new CircleOptions() 
     //  .center(cameraPosition.target) 
     //  .radius(geoRadius) 
     //  .strokeColor(Color.GREEN) 
     //  .fillColor(Color.BLUE)); 

     Toast.makeText(this, "Area: " + geoArea, Toast.LENGTH_SHORT).show(); 
    } 
} 

结果如下所示,并显示与由每个时间圆圈相机更改所覆盖的区域中的Toast

enter image description here

限制:

该示例图中的正圆View,但根据缩放级别,此圆不保证地理位置准确。

您可以看到,在高放大级别下,如果取消注释onCameraChange上的代码mMap.addCircle,则自定义视图绘制的圆与地理上精确的圆(基于相机目标和半径)之间存在巨大差异方法:

enter image description here

由所述地图(WGS84)的投影引起的这种差异,是在高缩放级别巨大的,并且在较低的缩放级别降低:

enter image description here

+0

完美!这是我一直在寻找的。关于局限性:我将此用作某些数据的图形表示,因此只需近似该区域就足够了。感谢您花时间逐步清楚地解释解决方案。 =) – TwiZtor

+0

很高兴帮助:)如果此解决方案完全回答您的问题,则可以考虑将其标记为接受的答案。 – antonio

+0

只要我测试一下就可以做到。 – TwiZtor