如何实现Google Map Marker平滑缩放?解决部分设备标记消失问题
Google Map Marker平滑缩放优化方案
问题根源分析
原实现存在几个容易导致Marker消失的问题:
- 两个独立的
ValueAnimator分别控制宽高缩放,易出现同步偏差,引发绘制异常 - 动画回调中重复调用
viewToDrawable(target)生成Drawable,再创建BitmapDescriptor,频繁的Bitmap创建/销毁会引发内存波动,部分设备上可能因绘制线程阻塞导致Marker短暂消失 - 手动控制帧率+
Choreographer.postFrameCallback的组合,和系统动画调度逻辑冲突,容易造成帧丢失
优化后的实现方案
以下是修复后的平滑缩放代码,解决了上述问题:
// 提前缓存原始Drawable,避免动画过程中重复创建 val originalDrawable = viewToDrawable(target) as BitmapDrawable val originalBitmap = originalDrawable.bitmap val originalWidth = originalBitmap.width val originalHeight = originalBitmap.height // 用单个ValueAnimator控制缩放比例,保证XY缩放同步 val scaleAnimator = ValueAnimator.ofFloat(anim.fromX, anim.toX) scaleAnimator.apply { duration = anim.duration repeatMode = anim.repeatMode repeatCount = anim.repeatCount addUpdateListener { animator -> val currentScale = animator.animatedValue as Float // 计算缩放后的尺寸 val scaledWidth = (originalWidth * currentScale).toInt() val scaledHeight = (originalHeight * currentScale).toInt() // 创建平滑缩放的Bitmap,启用双线性过滤提升画质 val scaledBitmap = Bitmap.createScaledBitmap( originalBitmap, scaledWidth, scaledHeight, true ) // 更新Marker图标 marker.setIcon(BitmapDescriptorFactory.fromBitmap(scaledBitmap)) // 回收临时Bitmap,避免内存占用过高 if (!scaledBitmap.isRecycled) { scaledBitmap.recycle() } } } animations.add(scaleAnimator)
额外优化建议
- 缓存前置:如果
viewToDrawable是将自定义View转为Drawable,建议提前将View绘制到Bitmap并缓存,不要在动画回调中重复执行,减少性能开销 - 锚点保持:缩放时可以配合
Marker.setAnchor(0.5f, 0.5f)(根据需求调整),保证Marker的锚点位置不变,避免缩放时出现偏移 - 批量处理:如果需要同时动画多个Marker,建议使用批量更新逻辑,减少对Google Map API的调用频率
- 异常兜底:可以在动画开始前保存原始Marker图标,动画结束后恢复,避免中间状态因异常导致图标为空
内容的提问来源于stack exchange,提问作者mengxw14
相关产品推荐
相关产品推荐

