使用自定义视图或 ImageView 的 Android Google Maps v2

4

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

目前我正在使用Maps v1来实现这个功能,效果很好,但Maps v2不适合做这个。

你可能会认为GroundOverlay或TileOverlay可能会起作用,但根据我从那些尝试使用它们的人所读到的,你必须在绘制下一张图像之前删除前一个图像,或者尝试将Bitmap图像绘制为标记或其他东西。 它必须具有良好的性能。

因此,我希望能够使用自定义视图或ImageView,并使用它的onDraw()方法绘制Bitmap,并在地图上可见并随地图移动。

就像:

<Outer Container>

    <fragment .. />

    <com.my.customView .. />

    or

    <ImageView .. />

</Outer Container>

我在网上寻找了有关使用Maps v2实现类似功能的详细示例,但是没有找到任何信息。
我在我的应用程序中使用了几个自定义视图,因此我对它们很熟悉,并且我已经获取了位图的边界框详细信息,我相信可以使用投影信息来帮助绘制它们。
另一个问题是如何调用invalidate()方法以便调用onDraw()方法。
我只需要一些示例代码,演示如何使用基于视图的对象的onDraw()方法,以便我可以尝试看看它是否有效,但是请不要尝试使用“GroundOverlay”、“TileOverlay”或“Marker”,非常感谢!
谢谢!
1个回答

6
如果您熟悉实现自定义视图,您可以创建一个扩展MapView类的自定义视图,以完全控制在视图画布上的绘制。但是由于MapView扩展了FrameLayout,它是ViewGroup,因此您应该覆盖dispatchDraw()方法,而不是onDraw()并在其中实现雷达绘制。就像这样:
@Override
public void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);
    canvas.save();
    drawRadarOverTheMap(canvas);
    canvas.restore();
}

您需要在每次地图移动/缩放/旋转时通过 invalidate() 调用它。要检测地图的移动/缩放/旋转,您需要使用 GoogleMap(确切地说是 GoogleMap.setOnCameraMoveListener() 方法)。您可以在自定义 MapView 类中声明 GoogleMap 对象并通过 setter 设置它,但最好是自定义 MapView 类实现 OnMapReadyCallback 接口并在 onMapReady() 回调中获取它。
基于 MapView 的自定义视图(例如 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);
        }
    }

}

你可以在 .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>

对于像 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();
    }

}

你应该得到类似于这样的东西:

Radar MapView

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

您还可以将ImageView放置在MapViewMapFragment上(例如在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>

ImageView上绘制(甚至只需设置)雷达图像。

非常感谢您的回答!我会去查看一下! - user1572522
谢谢你的回答Andrii!抱歉回复晚了,请问你有完整的示例项目吗?我在构建过程中遇到了一些问题。关于这方面的资料实在太少了。谢谢! - user1572522
@user1572522 只需创建一个带有空Activity的新项目,添加新类RadarMapView.java,并用答案中的代码替换MainActivity.javaactivity_main.xml的代码。答案中的源代码是完整且已就绪的(除了 {your_package_name}.MainActivity - 您应该将其替换为自己的)。 - Andrii Omelchenko
谢谢Andrii!我已经成功构建了。我使用的项目中的google-play-services.jar没有OnCameraMoveListener,所以我改用了OnCameraChangeListener并且它起作用了。感谢你的帮助! - user1572522

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