将 Android Google Maps v2 与自定义 View 或 ImageView 结合使用

use*_*522 4 android google-maps

基本上我希望能够使用谷歌地图 v2 在地图上绘制雷达图像,具有良好的性能并且位图图像没有闪烁或延迟。

我目前正在使用 Maps v1 来执行此操作,并且效果很好,但 Maps v2 不太适合这样做。

您可能会认为 GroundOverlay 或 TileOverlay 可能有用,但是根据我从尝试使用它们的人那里读到的内容,您必须在绘制下一张图像之前 remove() 前一张图像,或者尝试绘制一些杂乱无章的图像位图图像作为标记或其他东西。它必须具有良好的性能。

所以我希望能够使用自定义视图或 ImageView 并使用它的 onDraw() 绘制位图并使其在地图上可见并随之移动。

喜欢:

<Outer Container>

    <fragment .. />

    <com.my.customView .. />

    or

    <ImageView .. />

</Outer Container>
Run Code Online (Sandbox Code Playgroud)

我在网络上到处寻找有关如何使用 Maps v2 执行此类操作的详细信息的可能示例,但一无所获。

我在当前的应用程序中使用了几个自定义视图,所以我对它们很熟悉,并且我有位图的边界框详细信息,我很确定我可以使用投影信息来帮助绘制它们。

另一个问题是如何调用 invalidate() 以便调用 onDraw()。

我只需要一些示例代码来展示如何从某种基于 View 的对象中使用 onDraw(),我可以尝试查看它是否有效,但不尝试使用“GroundOverlay”、“TileOverlay”或“标记”,我真的很感激!

谢谢!

And*_*nko 5

如果您熟悉实现自定义视图,您可以创建自定义视图,该视图扩展MapView类以完全控制视图画布上的绘图。但是因为MapViewextends FrameLayoutwhich is ViewGroup,你应该覆盖dispatchDraw()方法,而不是onDraw()在它的雷达绘图中实现。类似的东西:

@Override
public void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);
    canvas.save();
    drawRadarOverTheMap(canvas);
    canvas.restore();
}
Run Code Online (Sandbox Code Playgroud)

并且您需要invalidate()在每次地图移动/缩放/旋转时调用它。要检测地图移动/缩放/旋转,您需要GoogleMap(正是GoogleMap.setOnCameraMoveListener()方法)。您可以GoogleMap在自定义 MapView 类中声明对象并通过 setter 设置它,但最好是自定义 MapView 类将实现OnMapReadyCallback接口并获取它onMapReady()回调中。

MapView-based 自定义视图(例如RadarMapView)的完整源代码可以是这样的:

public class RadarMapView extends MapView implements OnMapReadyCallback {

    private OnMapReadyCallback mMapReadyCallback;
    private GoogleMap mGoogleMap;
    private Marker mMarker;
    private Paint mPaintRadar;

    public RadarMapView(@NonNull Context context) {
        super(context);
        init();
    }

    public RadarMapView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RadarMapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public RadarMapView(@NonNull Context context, @Nullable GoogleMapOptions options) {
        super(context, options);
        init();
    }

    @Override
    public void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        canvas.save();
        drawRadarOverTheMap(canvas);
        canvas.restore();
    }

    private void drawRadarOverTheMap(Canvas canvas) {
        if (mGoogleMap == null) {
            return;
        }

        final float centerX = getX() + getWidth() / 2;
        final float centerY = getY() + getHeight() / 2;

        canvas.drawCircle(centerX, centerY, 150, mPaintRadar);
        canvas.drawCircle(centerX, centerY, 300, mPaintRadar);
        canvas.drawCircle(centerX, centerY, 450, mPaintRadar);
    }

    private void init() {
        setWillNotDraw(false);

        mPaintRadar = new Paint();
        mPaintRadar.setColor(Color.GREEN);
        mPaintRadar.setStyle(Paint.Style.STROKE);
        mPaintRadar.setStrokeWidth(10);
    }

    @Override
    public void getMapAsync(OnMapReadyCallback callback) {
        mMapReadyCallback = callback;
        super.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;
        mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
            @Override
            public void onCameraMove() {
                invalidate();
            }
        });
        if (mMapReadyCallback != null) {
            mMapReadyCallback.onMapReady(googleMap);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

你可以在.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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="{your_package_name}.MainActivity">

    <{your_package_name}.RadarMapView
        android:id="@+id/mapview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        />
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

对于MainActivity喜欢:

public class MainActivity extends AppCompatActivity {

    private static final String MAP_VIEW_BUNDLE_KEY = "MapViewBundleKey";

    private GoogleMap mGoogleMap;
    private RadarMapView mMapView;

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

        Bundle mapViewBundle = null;
        if (savedInstanceState != null) {
            mapViewBundle = savedInstanceState.getBundle(MAP_VIEW_BUNDLE_KEY);
        }

        mMapView = (RadarMapView) findViewById(R.id.mapview);
        mMapView.onCreate(mapViewBundle);
        mMapView.getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(GoogleMap googleMap) {
                mGoogleMap = googleMap;
            }
        });

    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        Bundle mapViewBundle = outState.getBundle(MAP_VIEW_BUNDLE_KEY);
        if (mapViewBundle == null) {
            mapViewBundle = new Bundle();
            outState.putBundle(MAP_VIEW_BUNDLE_KEY, mapViewBundle);
        }

        mMapView.onSaveInstanceState(mapViewBundle);
    }

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

    @Override
    protected void onStart() {
        super.onStart();
        mMapView.onStart();
    }

    @Override
    protected void onStop() {
        super.onStop();
        mMapView.onStop();
    }
    @Override
    protected void onPause() {
        mMapView.onPause();
        super.onPause();
    }
    @Override
    protected void onDestroy() {
        mMapView.onDestroy();
        super.onDestroy();
    }
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mMapView.onLowMemory();
    }

}
Run Code Online (Sandbox Code Playgroud)

你应该得到这样的东西:

雷达地图视图

您也可以通过canvas.drawBitmap()方法在自定义视图画布上绘制位图雷达图像。

你也可以放置ImageViewMapViewMapFragment(例如内RelativeLayout

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.MapFragment"
    />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:src="@drawable/radar"
    />

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

并在 上绘制(甚至只是设置)雷达图像ImageView