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

2024-02-12

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

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

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

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

Like:

<Outer Container>

    <fragment .. />

    <com.my.customView .. />

    or

    <ImageView .. />

</Outer Container>

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

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

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

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

Thanks!


如果你熟悉实现自定义视图 https://developer.android.com/training/custom-views/index.html,您可以创建扩展的自定义视图MapView https://developers.google.com/android/reference/com/google/android/gms/maps/MapView用于完全控制视图画布上的绘图的类。但是因为MapView延伸FrameLayout这是ViewGroup,你应该覆盖dispatchDraw() https://developer.android.com/reference/android/view/ViewGroup.html#dispatchDraw(android.graphics.Canvas)方法,不onDraw()并在其中实现雷达绘图。像这样的东西:

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

你需要通过调用它invalidate()在每张地图上移动/缩放/旋转。为了检测地图移动/缩放/旋转,您需要GoogleMap https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap(确切地GoogleMap.setOnCameraMoveListener() https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.html#setOnCameraMoveListener(com.google.android.gms.maps.GoogleMap.OnCameraMoveListener)方法)。您可以声明GoogleMap自定义 MapView 类中的对象并通过 setter 设置它,但如果自定义 MapView 类将实现更好OnMapReadyCallback https://developers.google.com/android/reference/com/google/android/gms/maps/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 file:

<?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>

for MainActivity like:

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() https://developer.android.com/reference/android/graphics/Canvas#drawbitmap method.

而且你还可以放置ImageView over MapView or MapFragment(例如在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.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 Android Google Maps v2 与自定义 View 或 ImageView 结合使用 的相关文章

随机推荐

  • 元素' aria-label='将 'tools:replace="Android:value"' 添加到 AndroidManifest 的 元素'> 将 'tools:replace="Android:value"' 添加到 AndroidManifest 的 元素

    我正在遵循 HeadFirst Android 开发教程 并在添加后遇到问题 私人 ActionBarDrawerToggle 抽屉切换 该控件已被弃用 因此我按照 Stack 上的说明通过将 com android support app
  • MySql 查询:包含 COUNT(id) == 0 的天数,但仅在过去 30 天内

    我正在执行一个查询 以获取过去 30 天内每天从数据库中生成的数量 但也需要标记没有构建的日子 在我的 WHERE 子句中 我使用 Submittime 来确定是否有构建 如何修改它以包含 COUNT id 0 但仅在过去 30 天内的日期
  • CORS 不适用于 Chrome

    我已经在服务器上设置了跨源资源共享 使用 CrossOriginFilter 的 Jetty 它在 IE8 和 Firefox 上完美运行 在 Chrome 上 它只是 没有 ajax url crossOriginURL type GET
  • Pandas 计算机每小时平均值并设置在间隔中间

    我想计算风速和风向时间序列的每小时平均值 但我想将时间设置为半小时 因此 14 00 到 15 00 之间的值的平均值将为 14 30 现在 我似乎只能在间隔的左侧或右侧得到它 这是我目前拥有的 ts g item replace seco
  • 无法下载eclipse插件

    我正在尝试下载 eclipse 的 kotlin 插件 我能够连接到 eclipse 市场 但是当我尝试下载它时 出现错误 Unable to read repository at https dl bintray com jetbrain
  • 对 Pandas 数据框中的行对应用函数

    我是 pandas dataframe 的新手 我想应用一个在同一列中获取几行的函数 就像当您应用函数 diff 时一样 但我想计算文本之间的距离 所以我定义了一个测量距离的函数 我尝试使用 apply 但我不知道如何选择几行 下面我展示了
  • 石墨总结数据点

    我在用着graphite http graphite wikidot com 收集数据 我想检索一段时间内某些事件的总数 比如说 每周的登录次数 但是 我只需要总数 不需要查看它如何随时间变化 当我使用类似的东西时from 1w targe
  • Symfony 5 Api 测试 createClient() LogicalException

    正如标题所示 我正在使用 Symfony 5 构建一个 API 我有一些控制器需要不同的用户权限 我想测试它们 所以我决定创建两个具有不同角色的用户用于测试目的 ROLE USER and ROLE ADMIN 当前的代码是这样的 注意 这
  • MySql:显示列但排除除字段名称之外的所有内容

    我想将表的字段名称从 MySql 提取到 python 中 我知道 show columns from project 将工作 我读到您可以添加 WHERE 以将其限制为某些字段 但我找不到如何仅返回列名而不返回类型 键 空 额外信息的示例
  • Rails.cache.clear 和 rake tmp:cache:clear 有什么区别?

    这两个命令等效吗 如果不是 有什么区别 rake 任务仅清除存储在文件系统中的文件 Rails root tmp cache 这是该任务的代码 namespace cache do desc Clears all files and dir
  • 需要了解SemaphoreSlim的用法

    这是我的代码 但我不明白是什么SemaphoreSlim是在做 async Task WorkerMainAsync SemaphoreSlim ss new SemaphoreSlim 10 List
  • ASP.NET / IIS 远程调试 - DEBUG 动词

    我正在寻找有关 DEBUG HTTP 动词的详细信息 我很清楚这是用于远程调试 尽管我什至不确定它是用于 IIS 还是 ASP NET 如果我想直接访问此界面 即不通过 Visual Studio 而是手动发送这些命令 我需要知道什么 它的
  • 我需要为初级程序员进行一些简单的逻辑/编程练习[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我目前正在教授员工 ECMA 脚本 因为维护我们使用的工作流程系统需要它 并且我需要一些挑战来用作练习 我们已经涵盖了大部分语言 他现在非
  • 为遗留库创建代码契约

    最终目标是为驻留在我无法控制的外部程序集中的类指定契约 即我不能直接向该类添加契约 到目前为止我已经尝试过 ContractClassFor属性 不起作用 因为目标类必须指向合约类 通过对自动生成的程序集进行逆向工程 手动构建合同引用程序集
  • Bingpreview 使电子邮件中的一次性链接失效

    Outlook com 似乎使用必应预览 https www bing com webmaster help which crawlers does bing use 8c184ec0爬虫来爬行电子邮件中的链接 但在打开电子邮件后 用户有机
  • GCC 选项强制执行 Ansi C 标准检查?

    我应该使用哪些 gcc 选项来强制执行 ANSI C C99 警告 错误 gcc GCC 3 4 2 mingw 特殊 我在用着 gcc 学究式 ansi std c99 它是否正确 The ansi标志是同义词 std c89 flag
  • CakePHP 2.1.0:如何创建“停机维护”页面

    我正在尝试实现类似的东西马克 斯托里的 停机维护 页面 http mark story com posts view quick and dirty down for maintenance page with cakephp使用 Cake
  • 代码中未初始化的指针

    我正在学习 C 我发现指针如果未初始化可能会指向内存中的随机位置 并产生内存可能被其他程序使用的问题 现在 如果是这种情况 我们就不应该在代码的任何部分包含这一行 int ptr 相反 我们应该有类似的东西 int ptr NULL Is
  • Spring 批处理:FlatFileItemWriter 标头从未被调用

    我的 FlatFileItemWriter 回调有一个奇怪的问题 我有一个自定义 ItemWriter 实现 FlatFileFooterCallback 和 FlatFileHeaderCallback 因此 我在 FlatFileIte
  • 将 Android Google Maps v2 与自定义 View 或 ImageView 结合使用

    基本上我希望能够使用 Google 地图 v2 在地图上绘制雷达图像 并使用良好的 性能并且位图图像没有闪烁或延迟 我目前正在使用 Maps v1 来执行此操作 效果很好 但是 Maps v2 不太适合这样做 您可能认为 GroundOve