【问题标题】:Using Android Google Maps v2 with custom View or ImageView使用带有自定义 View 或 ImageView 的 Android Google Maps v2
【发布时间】:2018-05-27 21:22:06
【问题描述】:

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

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

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

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

喜欢:

<Outer Container>

    <fragment .. />

    <com.my.customView .. />

    or

    <ImageView .. />

</Outer Container>

我在网上到处寻找可能的例子 有关如何使用 Maps v2 执行此类操作的详细信息,但已找到 什么都没有。

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

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

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

谢谢!

【问题讨论】:

    标签: android google-maps


    【解决方案1】:

    如果您熟悉implementing custom view,您可以创建扩展MapView 类的自定义视图,以便完全控制在视图画布上绘图。但是因为MapView 扩展了FrameLayoutViewGroup,所以您应该覆盖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();
        }
    
    }
    

    你应该得到类似的东西:

    您还可以通过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 只需使用空 Activity 创建新项目添加新类 RadarMapView.java 并替换 MainActivity.javaactivity_main.xml 代码由答案代码。答案中的源代码是完整的({your_package_name}.MainActivity 除外 - 你应该用你的替换它)。
    • 谢谢安德烈!我得到它来建造。我使用该项目构建的 google-play-services.jar 没有 OnCameraMoveListener,因此我将其更改为使用 OnCameraChangeListener 并且它有效。感谢您的帮助!
    猜你喜欢
    • 2012-11-25
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 1970-01-01
    • 2013-01-05
    相关资源
    最近更新 更多