将动画添加为Marker google maps android

时间:2018-05-05 23:19:40

标签: android google-maps animation

我想在地图中添加动画作为“当前标记选中”,如下所示:

enter image description here

动画是LottieAnimation资源(从ImageView扩展而来)。

我一直在搜索谷歌地图开发者文档说我只能使用Bitmap资源作为标记。我试图将这个转换为位图,但没有成功。

Uber或Lyft有一些动画作为标记或当前位置,所以他们如何实现这一目标?

或者他们是否有可能在不使用标记属性的情况下收听地图移动并更新其标记的位置?

1 个答案:

答案 0 :(得分:1)

据我所知,Google地图标记和InfoWindow在地图上绘制为平面位图。所以你不能做动画,组件触摸交互,甚至不能正式在它们周围画一个阴影。

Uber应用程序使用放置在地图顶部的不同图层(您可以尝试在地图上做一些手势,看看标记移动但有点延迟)。这并不容易,因为您必须捕捉每个地图的手势并相应地为叠加视图设置动画。我之前尝试过,但是做了太多工作,我把它留在了后面。

使用Circle

ValueAnimator可以实现您的脉冲效果
private @ColorInt int mPulseEffectColor;
private int[] mPulseEffectColorElements;
private ValueAnimator mPulseEffectAnimator;
private Circle mPulseCircle;


private void initPulseEffect() {
    mPulseEffectColor = ContextCompat.getColor(mContext, R.color.pink);
    mPulseEffectColorElements = new int[] {
            Color.red(mPulseEffectColor),
            Color.green(mPulseEffectColor),
            Color.blue(mPulseEffectColor)
    };

    mPulseEffectAnimator = ValueAnimator.ofFloat(0, calculatePulseRadius(current_map_zoom_level));
    mPulseEffectAnimator.setStartDelay(3000);
    mPulseEffectAnimator.setDuration(400);
    mPulseEffectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
}

根据地图的缩放级别计算半径

private static float calculatePulseRadius(float zoomLevel) {
    return (float) Math.pow(2, 16 - zoomLevel) * 160;
}

注册OnCameraIdleListener以收听地图的缩放更改

@Override
public void onCameraIdle() {
    CameraPosition cameraPosition = mMap.getCameraPosition();
    if (mPulseEffectAnimator != null)
        mPulseEffectAnimator.setFloatValues(0, calculatePulseRadius(cameraPosition.zoom));
}

开始动画

private void startPulseAnimation() {
    if (mPulseCircle != null)
        mPulseCircle.remove();

    if (mPulseEffectAnimator != null) {
        mPulseEffectAnimator.removeAllUpdateListeners();
        mPulseEffectAnimator.removeAllListeners();
        mPulseEffectAnimator.end();
    }

    if (your_marker_coordinate != null) {
        mPulseCircle = mMap.addCircle(new CircleOptions()
                .center(your_marker_coordinate)
                .radius(0).strokeWidth(0)
                .fillColor(mPulseEffectColor));
        mPulseEffectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                if (mPulseCircle == null)
                    return;

                int alpha = (int) ((1 - valueAnimator.getAnimatedFraction()) * 128);
                mPulseCircle.setFillColor(Color.argb(alpha,
                        mPulseEffectColorElements[0], mPulseEffectColorElements[1], mPulseEffectColorElements[2]));
                mPulseCircle.setRadius((float) valueAnimator.getAnimatedValue());
            }
        });
        mPulseEffectAnimator.addListener(new AnimatorListenerAdapter {
            @Override
            public void onAnimationEnd(Animator animation) {
                mPulseEffectAnimator.setStartDelay(2000);
                mPulseEffectAnimator.start();
            }
        });
        mPulseEffectAnimator.start();
    }
}

说明:

  • 使用calculatePulseRadius重新计算地图缩放级别的半径基数,因为圆的半径是以实际距离来衡量的。
  • 使用int[] mPulseEffectColorElements存储圆圈颜色的r,g,b,这样我就不必每帧重新创建颜色。我只想更改alpha值
  • 听Animator结束并延迟再次启动。

此代码一次仅适用于1个圆圈,多个圆圈需要更多的工作但需要相同的逻辑。

结果:

demo