Android Google Maps添加Lottie动画作为选中标记的实现咨询
嘿,这个问题我做地图功能时也踩过坑,刚好能给你一些实用的解决方案!Google Maps的Marker确实只支持静态Bitmap,直接转Lottie的Bitmap只能拿到单帧,没法保留动画效果。Uber、Lyft这类大厂的动态标记,大多是用自定义覆盖视图+地图相机监听的方式实现的,下面给你拆解两种可行的方案:
方案一:自定义OverlayView(推荐,大厂同款)
这种方式是绕过Google Maps的Marker组件,直接把你的LottieAnimationView作为地图的子视图,通过监听地图移动实时更新它的位置,完全自定义动画效果:
添加LottieView到地图布局
把你的LottieAnimationView放在MapView的上层(比如用FrameLayout包裹MapView和LottieView),初始设置为GONE,选中标记时再显示。监听地图相机移动,实时更新位置
注册地图的OnCameraMoveListener和OnCameraIdleListener,在回调里把目标经纬度转换成屏幕坐标,然后调整LottieView的位置(注意锚点偏移,比如Marker默认锚点是底部中心,所以要把View的中心对准坐标点的底部):// 初始化地图时设置监听 map.setOnCameraMoveListener { updateLottieMarkerPosition(selectedLatLng) } map.setOnCameraIdleListener { updateLottieMarkerPosition(selectedLatLng) } // 更新位置的方法 private fun updateLottieMarkerPosition(targetLatLng: LatLng) { val screenPoint = map.projection.toScreenLocation(targetLatLng) // 调整位置:让LottieView的底部中心对准坐标点 lottieMarkerView.x = screenPoint.x - lottieMarkerView.width / 2f lottieMarkerView.y = screenPoint.y - lottieMarkerView.height.toFloat() lottieMarkerView.visibility = View.VISIBLE }处理动画生命周期
在页面的onResume时启动Lottie动画,onPause时暂停,避免后台浪费资源;当标记移出地图可视区域时,记得隐藏LottieView。
这种方式的优势是动画流畅度拉满,完全支持Lottie的所有交互和动态效果,也是Uber、Lyft实现当前位置脉冲、方向动画的核心方式。
方案二:逐帧更新Marker的Icon(适合简单动画)
如果一定要用Google Maps自带的Marker,可以通过监听Lottie的帧回调,把每一帧转成Bitmap更新Marker的Icon:
监听Lottie的帧更新
给LottieAnimationView添加动画更新监听,在每帧回调里生成当前帧的Bitmap,然后更新Marker的Icon:lottieAnimationView.addAnimatorUpdateListener { // 把Lottie当前帧转成Bitmap(需要自定义实现或用第三方工具) val bitmap = lottieAnimationView.getFrameBitmap() val icon = BitmapDescriptorFactory.fromBitmap(bitmap) selectedMarker?.setIcon(icon) }注:
getFrameBitmap()需要你自己实现,比如通过Canvas绘制Lottie的当前帧到Bitmap上。注意性能问题
这种方式会频繁更新Marker的Icon,在低性能设备上可能出现卡顿,而且Lottie的复杂动画会加重CPU负担,所以只适合简单的循环动画。
总结
- 追求流畅度和复杂动画:选方案一(OverlayView+相机监听),这是大厂的标准做法;
- 简单动画且不想改动现有Marker逻辑:选方案二,但要做好性能优化。
内容的提问来源于stack exchange,提问作者Diego Sebastián García

