实现Google Maps Marker显示放大、隐藏缩小动画(仿Uber效果)
实现Google Maps Marker的缩放动画(类似Uber车型选择效果)
我明白你想要实现类似Uber的Marker动画:添加时从无到有放大显示,移除时缩小消失。下面我会基于你现有的代码,给出完整的实现方案。
核心思路
利用Android的ValueAnimator动态控制Marker图标的缩放比例,在添加Marker时执行从0到1的放大动画,在需要隐藏Marker时执行从1到0的缩小动画,动画过程中实时更新Marker的图标,模拟出平滑的弹出/消失效果。
步骤1:封装通用的Marker缩放动画方法
先写一个可复用的动画工具方法,方便在添加和隐藏Marker时调用:
private void animateMarkerScale(final Marker marker, final Bitmap originalIcon, float startScale, float endScale, long duration, final OnAnimationEndListener listener) { ValueAnimator animator = ValueAnimator.ofFloat(startScale, endScale); animator.setDuration(duration); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float scale = (float) animation.getAnimatedValue(); // 创建缩放后的Bitmap Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalIcon, (int) (originalIcon.getWidth() * scale), (int) (originalIcon.getHeight() * scale), true); // 更新Marker图标 marker.setIcon(BitmapDescriptorFactory.fromBitmap(scaledBitmap)); // 回收临时Bitmap避免内存泄漏 if (scale != 1f && !scaledBitmap.isRecycled()) { scaledBitmap.recycle(); } } }); animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {} @Override public void onAnimationEnd(Animator animation) { if (listener != null) { listener.onAnimationEnd(); } } @Override public void onAnimationCancel(Animator animation) {} @Override public void onAnimationRepeat(Animator animation) {} }); animator.start(); } // 定义动画结束回调接口,用于处理动画完成后的逻辑 public interface OnAnimationEndListener { void onAnimationEnd(); }
步骤2:修改添加Marker的逻辑(实现放大显示动画)
在你的addDriver方法中,加载原始图标后,先让Marker以极小尺寸显示(视觉上隐藏),再启动放大动画:
private void addDriver(JSONArray jsonArray) { // 加载原始Marker图标(替换成你的实际图标资源) final Bitmap originalMarkerIcon = BitmapFactory.decodeResource(getResources(), R.drawable.icon); for (int i = 0; i < jsonArray.length(); i++) { String userId = jsonArray.optJSONObject(i).optString("user_id"); if (!(markersList.containsKey(userId))) { LatLng position = new LatLng( Double.parseDouble(jsonArray.optJSONObject(i).optString("user_lat")), Double.parseDouble(jsonArray.optJSONObject(i).optString("user_long")) ); // 创建初始状态的Marker:用1x1的极小图标隐藏起来 Bitmap initialScaledIcon = Bitmap.createScaledBitmap(originalMarkerIcon, 1, 1, true); final Marker marker = mGoogleMap.addMarker(new MarkerOptions() .position(position) .snippet(userId) .icon(BitmapDescriptorFactory.fromBitmap(initialScaledIcon))); marker.setTag(jsonArray.optJSONObject(i).optString("vehicle_type")); // 回收初始临时Bitmap if (!initialScaledIcon.isRecycled()) { initialScaledIcon.recycle(); } markersList.put(userId, marker); // 启动放大动画:从0到1,时长300ms(这个速度贴近Uber的效果,可按需调整) animateMarkerScale(marker, originalMarkerIcon, 0f, 1f, 300, null); } } }
步骤3:实现Marker缩小隐藏的逻辑
当你需要移除某个Marker时(比如切换车型),先执行缩小动画,动画结束后再移除Marker:
private void removeDriverWithAnimation(String userId) { final Marker marker = markersList.get(userId); if (marker == null) return; Bitmap originalIcon = BitmapFactory.decodeResource(getResources(), R.drawable.icon); // 启动缩小动画:从1到0,时长300ms animateMarkerScale(marker, originalIcon, 1f, 0f, 300, new OnAnimationEndListener() { @Override public void onAnimationEnd() { // 动画结束后彻底移除Marker并从列表中删除 marker.remove(); markersList.remove(userId); } }); }
注意事项
- 内存管理:动画过程中会创建临时Bitmap,记得在合适时机回收,避免内存泄漏。
- 图标清晰度:确保你的Marker图标是高分辨率的,避免缩放后出现模糊。
- 性能优化:如果同时有大量Marker需要执行动画,建议控制并发动画的数量,避免界面卡顿。
这样修改后,你的Marker就会像Uber那样,添加时平滑放大出现,移除时缩小消失啦!
内容的提问来源于stack exchange,提问作者prashant jaiswal
相关产品推荐
相关产品推荐

