You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中如何将AnimatedVectorDrawable用作地图标记?

在Android中使用AnimatedVectorDrawable作为地图标记的可行方案

我来帮你搞定这个问题!你遇到的情况很典型——普通VectorDrawable转Bitmap能正常显示,但AnimatedVectorDrawable不行,核心原因是刚初始化的AnimatedVectorDrawable还没有绘制任何帧,直接调用draw(canvas)得到的是一张完全透明的Bitmap,地图上自然看不到标记。下面给你两种可行的实现方案,分别对应静态显示第一帧和动态播放动画的需求。

方案一:静态显示AnimatedVectorDrawable的第一帧

如果只需要显示动画的初始状态,我们可以先让AnimatedVectorDrawable完成初始化并绘制第一帧,再生成Bitmap。这里可以借助临时View来触发绘制流程:

private void addStaticAnimatedMarker(LatLng pickuplatlng) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        AnimatedVectorDrawable avd = (AnimatedVectorDrawable) getDrawable(R.drawable.setpickuplocationdrawable);
        int width = avd.getIntrinsicWidth();
        int height = avd.getIntrinsicHeight();
        
        // 创建临时View来承载Drawable,触发绘制准备
        View tempView = new View(this);
        tempView.setBackground(avd);
        tempView.measure(
            View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
            View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
        );
        tempView.layout(0, 0, width, height);
        
        // 等待View完成绘制后生成Bitmap并添加标记
        tempView.post(() -> {
            Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            tempView.draw(canvas);
            
            MarkerOptions marker1 = new MarkerOptions()
                .icon(BitmapDescriptorFactory.fromBitmap(bitmap))
                .position(pickuplatlng)
                .title("Marker at place1");
            googleMap.addMarker(marker1);
        });
    } else {
        // 低版本直接用资源ID生成(不过低版本不支持AnimatedVectorDrawable,这里做兼容)
        MarkerOptions marker1 = new MarkerOptions()
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.setpickuplocationdrawable))
            .position(pickuplatlng)
            .title("Marker at place1");
        googleMap.addMarker(marker1);
    }
}

方案二:让地图标记动态播放动画

如果需要标记持续播放AnimatedVectorDrawable的动画,我们需要定期更新Marker的Icon,同步动画的每一帧:

private Marker animatedMarker;
private ValueAnimator animator;

private void addDynamicAnimatedMarker(LatLng pickuplatlng) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        AnimatedVectorDrawable avd = (AnimatedVectorDrawable) getDrawable(R.drawable.setpickuplocationdrawable);
        int width = avd.getIntrinsicWidth();
        int height = avd.getIntrinsicHeight();
        avd.setBounds(0, 0, width, height);
        
        // 生成初始帧Bitmap并添加Marker
        Bitmap initialBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas initialCanvas = new Canvas(initialBitmap);
        avd.draw(initialCanvas);
        
        animatedMarker = googleMap.addMarker(new MarkerOptions()
            .icon(BitmapDescriptorFactory.fromBitmap(initialBitmap))
            .position(pickuplatlng)
            .title("Animated Marker"));
        
        // 启动动画并同步更新Marker的Icon
        avd.start();
        animator = ValueAnimator.ofFloat(0f, 1f);
        animator.setDuration(avd.getTotalDuration());
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.addUpdateListener(animation -> {
            Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            avd.draw(canvas);
            animatedMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
        });
        animator.start();
    } else {
        // 低版本兼容逻辑
        MarkerOptions marker1 = new MarkerOptions()
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.setpickuplocationdrawable))
            .position(pickuplatlng)
            .title("Marker at place1");
        googleMap.addMarker(marker1);
    }
}

// 记得在页面销毁/暂停时停止动画,避免内存泄漏
@Override
protected void onPause() {
    super.onPause();
    if (animator != null) {
        animator.cancel();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (animatedMarker != null) {
        animatedMarker.remove();
    }
}

关键说明

  • 为什么你的原始代码不行?因为AnimatedVectorDrawable在刚实例化时,内部动画还未启动,没有任何像素被绘制到画布上,生成的Bitmap是完全透明的,所以地图上看不到标记。
  • 动态方案中,每次更新都会生成新的Bitmap,如果你担心性能,可以考虑复用Bitmap对象,减少内存开销。

内容的提问来源于stack exchange,提问作者Basit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:54:11