抖动的Google地图标记动画

时间:2015-05-26 20:54:41

标签: android google-maps animation google-maps-markers

我正在尝试在Google地图上制作标记。我遇到的问题是标记在动画时的表现。标记沿着给定的一组点移动,但是它们开始相当猛烈地摇动,或者它们将沿着设定路径移动并且看起来是橡皮筋,或者跳回到原始起始位置。

以前有人处理过这个问题吗?如果是这样,你是如何修复它的?我目前正在使用由Google开发人员提供的稍微修改过的代码来处理动画。

更新:我认为问题是由于尝试在给定标记上同时运行多个动画而引起的。这导致标记在所有新/旧位置之间来回反弹。

这是处理动画调用的代码,该方法传递一个LatLng列表,代表标记应遵循的路径。

public void animateMarker(String key, List<LatLng> latlngList) {
    AnimateCarObj animateCarObj = animateCarObjMap.get(key);
    Marker marker = markersHashMap.get(key);

    if (marker != null) {

        LatLng prev = new LatLng(0, 0);
        for (LatLng latlng : latlngList) {
            if (!(latlng.equals(prev))) {
                try {
                    LatLngInterpolator latlonInter = new LinearFixed();
                    latlonInter.interpolate(1, animateCarObj.getGps1(), latlng);

                    MarkerAnimation.animateMarker(latlngList.size(), marker, latlng, latlonInter);
                    prev = latlng;

                } catch (Exception e) {
                    Log.e(TAG, "EXCEPTION: " + e.getMessage());
                    e.printStackTrace();
                }
            }
        }
    }
}

MarkerAnimation Class ,我修改了这个类以获取一个名为&#34;&#34;的整数值,这样动画将以均匀的速度通过所有点,而不管通过请求返回多少个点。在此示例中,它使用默认值3,将其乘以10000 ms,然后将其除以步数。

public class MarkerAnimation {

    public static void animateMarker(int steps, final Marker marker, final LatLng finalPosition,
                                                                        final LatLngInterpolator latLngInterpolator) {
        if (marker == null || finalPosition == null || latLngInterpolator == null) { return; }
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
            animateMarkerToGB(steps, marker, finalPosition, latLngInterpolator);
        } else {
            animateMarkerToICS(steps, marker, finalPosition, latLngInterpolator);
        }
    }

    public static void animateMarkerToGB(int steps, final Marker marker, final LatLng finalPosition,
                                                                                final LatLngInterpolator latLngInterpolator) {
        final LatLng startPosition = marker.getPosition();
        final Handler handler = new Handler();
        final long start = SystemClock.uptimeMillis();
        final Interpolator interpolator = new AccelerateDecelerateInterpolator();
        final float durationInMs = (CarListStore.DEFAULT_ALIVE_COUNT * 10000) / steps;

        handler.post(new Runnable() {
            long elapsed;
            float t;
            float v;

            @Override
            public void run() {
                // Calculate progress using interpolator
                elapsed = SystemClock.uptimeMillis() - start;
                t = elapsed / durationInMs;
                v = interpolator.getInterpolation(t);

                marker.setPosition(latLngInterpolator.interpolate(v, startPosition, finalPosition));

                // Repeat till progress is complete.
                if (t < 1) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                }
            }
        });
    }

    /*  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        public static void animateMarkerToHC(final Marker marker, final LatLng finalPosition,
                                                                                    final LatLngInterpolator latLngInterpolator) {
            final LatLng startPosition = marker.getPosition();

            ValueAnimator valueAnimator = new ValueAnimator();
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float v = animation.getAnimatedFraction();
                    LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, finalPosition);
                    marker.setPosition(newPosition);
                }
            });
            valueAnimator.setFloatValues(0, 1); // Ignored.
            valueAnimator.setDuration(3000);
            valueAnimator.start();
        }*/

    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    public static void animateMarkerToICS(int steps, Marker marker, LatLng finalPosition, final LatLngInterpolator latLngInterpolator) {
        TypeEvaluator<LatLng> typeEvaluator = new TypeEvaluator<LatLng>() {
            @Override
            public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
                return latLngInterpolator.interpolate(fraction, startValue, endValue);
            }
        };
        Property<Marker, LatLng> property = Property.of(Marker.class, LatLng.class, "position");
        ObjectAnimator animator = ObjectAnimator.ofObject(marker, property, typeEvaluator, finalPosition);
        animator.setDuration((CarListStore.DEFAULT_ALIVE_COUNT * 10000) / steps);
        animator.start();
    }
}

2 个答案:

答案 0 :(得分:0)

您正在进行异步调用,因为您在制造商上有多个动画,您将面临紧张情绪。

使用同步方法,即[valueAnimator][1] - 您已在代码中注释掉它。在文档中观看this video,它解释了为什么以及何时使用它。

希望它有所帮助!

答案 1 :(得分:0)

我的方法是使用处理程序安排Runnable,以便它可以有一些回调来调用通知动画完成。一旦从上一个动画处理程序获得OnComplete回调,就会保留排队标记位置的链接列表。延迟runnable从队列中弹出下一个latlng对象并运行动画。

在ICS的每种动画方法中animator.start()注册后的HC使用handler.postDelayed()延迟runnable,其中延迟是动画的完全持续时间