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
相关产品推荐
相关产品推荐

