android中的自定义,禁用和空白地图

时间:2016-03-16 08:48:46

标签: android google-maps maps

我想在地图上只显示标记的半径部分,而地图的其余部分必须为空白。 就像标记半径是5公里并且我希望只有地图的半径部分必须对用户可见,并且地图的其余部分必须为空白。

我已阅读有关Google地图叠加层的信息,还搜索了各种类似于MapBox和Skobbler的SDK,但它们都没有提供我想要的功能。

Here is the image which will explain how i want the map look like.

在图像中,您可以看到标记周围只有部分可见,其余部分为空白。我想在android Maps中实现这个功能。

如果有人有任何解决方案或想法,请告诉我。

感谢。

1 个答案:

答案 0 :(得分:3)

您可以在隐藏它的地图上添加View并在其上绘制一个圆圈,以便仅显示所需的位置。

我的答案基于

MapsActivity:

public class MapsActivity extends FragmentActivity implements GoogleMap.OnCameraChangeListener {
    private GoogleMap mMap;
    private HideOverlayView hideView;
    private List<Marker> visibleMarkers = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);

        hideView = (HideOverlayView) findViewById(R.id.hideview);

        setUpMapIfNeeded();
    }

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

    @SuppressLint("NewApi")
    private void setUpMapIfNeeded() {
        if (mMap == null) {
            final SupportMapFragment f = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
            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.getUiSettings().setMyLocationButtonEnabled(true);
        mMap.setMyLocationEnabled(true);
        mMap.setOnCameraChangeListener(this);

        mMap.moveCamera(CameraUpdateFactory.newCameraPosition(
                CameraPosition.fromLatLngZoom(new LatLng(40.22861, -3.95567), 15)));

        visibleMarkers.add(mMap.addMarker(new MarkerOptions().position(
                new LatLng(40.22861, -3.95567))));
        visibleMarkers.add(mMap.addMarker(new MarkerOptions().position(
                new LatLng(40.22977, -3.95338))));
    }

    @Override
    public void onCameraChange(final CameraPosition cameraPosition) {
        List<Point> visiblePoints = new ArrayList<>();
        Projection projection = mMap.getProjection();

        for (Marker visibleMarker : visibleMarkers) {
            visiblePoints.add(projection.toScreenLocation(visibleMarker.getPosition()));
        }

        float radius = 150f; // meters
        Point centerPoint = projection.toScreenLocation(cameraPosition.target);
        Point radiusPoint = projection.toScreenLocation(
                SphericalUtil.computeOffset(cameraPosition.target, radius, 90));

        float radiusPx = (float) Math.sqrt(Math.pow(centerPoint.x - radiusPoint.x, 2));

        hideView.reDraw(visiblePoints, radiusPx);
    }
}

HideOverlayView:

public class HideOverlayView extends LinearLayout {
    private Bitmap windowFrame;
    private float radius = 0f;
    private List<Point> points;

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

    public HideOverlayView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

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

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

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

    public void reDraw(List<Point> points, float radius) {
        this.points = points;
        this.radius = radius;

        invalidate();
    }

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

        RectF outerRectangle = new RectF(0, 0, getWidth(), getHeight());
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.BLACK);
        osCanvas.drawRect(outerRectangle, paint);

        if (radius > 0 && points != null) {
            for (Point point : points) {
                paint.setColor(Color.TRANSPARENT);
                paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
                paint.setStyle(Paint.Style.FILL);
                osCanvas.drawCircle(point.x, point.y, radius, 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;
    }
}

activity_maps.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                xmlns:tools="http://schemas.android.com/tools"
                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.HideOverlayView
        android:id="@+id/hideview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        app:radius="150dp"/>
</RelativeLayout>

<强>结果:

enter image description here

<强>限制:

  • 此解决方案仅更新HideOverlayView上的onCameraChange,因此当用户缩放或平移地图时,可以显示地图上的其他位置
  • 计算半径的计算不考虑地图的旋转和倾斜