地图视图中平滑缩放

6
当我使用MapController.setZoom(x)时,例如从级别5缩放到15,缩放非常快,新级别的地图瓦片经常没有加载完成。这对用户来说不是很好。有没有Maps内置函数可以将缩放变慢以便瓦片可以在达到15级之前被加载,或者至少几乎加载完成呢?最好的问候。P

2
速度动画化的一个巨大优势是:减少了无用的加载图像数量。当使用@1ka和@Reuben提供的示例时,可能会在3G / UMTS网络上产生大量位图加载调用,然后在350毫秒后被丢弃。这是对带宽的浪费,有时也是用户纯粹的金钱浪费。还要注意,即使在PC浏览器中,谷歌地图也是这样工作的,每个人都习惯了这种方式。没有人期望在切换显示位置时地图已经加载完成。 - WarrenFaith
2个回答

8

一种更简单的方法是利用MapController.zoomIn()方法,该方法提供了一些简单的动画来缩放一个级别。

下面是一些代码:

    // a Quick runnable to zoom in
    int zoomLevel = mapView.getZoomLevel();
    int targetZoomLevel = 18;

    long delay = 0;
    while (zoomLevel++ < targetZoomLevel) {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mapController.zoomIn();
            }
        }, delay);

        delay += 350; // Change this to whatever is good on the device
    }

它的作用是创建一系列延迟运行的可运行对象,每个对象都会在前一个对象之后350毫秒调用zoomIn()函数。
这假设您已经将名为“handler”的处理程序附加到了主UI线程上。
:-)

你也可以在接近18级时增加更长的延迟,以给予减速的感觉。 - SoftWyer
关于WarrenFaith对带宽的评论,上述内容与用户手动使用屏幕按钮缩放视图没有任何区别。延迟350毫秒后我得到了持续的缩放,但没有图像渲染。我认为MapView足够聪明,在请求瓷砖之前会等待所有活动停止。但我不确定。 - SoftWyer

0

这个没有简单的方式。但是,我可以帮助你。

首先,这里有一个我个人实用类的免费礼物,Tween.java:

import android.os.Handler;

public class Tween {

    public static interface TweenCallback {
        public void onTick(float time, long duration);
        public void onFinished();
    }

    long start;
    long duration;
    Handler handler;
    TweenCallback callback;

    public Tween(TweenCallback callback) {      
        handler = new Handler();
        this.callback = callback;
    }
    public void start(final int duration) {
        start = android.os.SystemClock.uptimeMillis();
        this.duration = duration;
        tickRunnable.run();
    }
    public void stop() {
        handler.removeCallbacks(tickRunnable);
    }
    Runnable tickRunnable= new Runnable() {
        public void run() {
            long now = android.os.SystemClock.uptimeMillis();
            float time = now - start;
            boolean finished = (time >= duration);
            if (finished) {
                time = duration;
            }
            callback.onTick(time, duration);
            if (!finished) {
                handler.post(tickRunnable);
            }
            else {
                callback.onFinished();
            }
        }
    };

    //
    // Tweening functions. The 4 parameters are :
    //
    //  t - time, ranges from 0 to d
    //  b - begin, i.e. the initial value for the quantity being changed over time
    //  c - change, the amount b will be changed by at the end
    //  d - duration, of the transition, normally in milliseconds. 
    //
    // All were adapted from http://jstween.sourceforge.net/Tween.js 
    //
    public static float strongEaseInOut(float t, float b, float c, float d) {
        t/=d/2; 
        if (t < 1) return c/2*t*t*t*t*t + b;
        return c/2*((t-=2)*t*t*t*t + 2) + b;
    }
    public static float regularEaseIn(float t, float b, float c, float d) {
        return c*(t/=d)*t + b;
    }
    public static float strongEaseIn(float t, float b, float c, float d) {
        return c*(t/=d)*t*t*t*t + b;
    }
}

我建议您使用MapController.zoomToSpan()与Tween结合使用...这里是一些完全未经测试的代码,应该可以工作,也许需要微调,您只需传递目标纬度和经度跨度即可。
public void slowZoom(int latE6spanTarget, int lonE6spanTarget) {
    final float initialLatE6span = mapView.getLatitudeSpan();
    final float initialLonE6span = mapView.getLongitudeSpan();
    final float latSpanChange = (float)(latE6spanTarget - initialLatE6span);
    final float lonSpanChange = (float)(lonE6spanTarget - initialLonE6span);
    Tween tween = new Tween(new Tween.TweenCallback() {
        public void onTick(float time, long duration) {
            float latSpan = Tween.strongEaseIn(time, initialLatE6span, latSpanChange, duration);
            float lonSpan = Tween.strongEaseIn(time, initialLonE6span, lonSpanChange, duration);
            mapView.getController().zoomToSpan((int)latSpan, (int)lonSpan);
        }
        public void onFinished() {
        }
    });
    tween.start(5000);
}

谢谢Reuben!我已经尝试过了,但是在每个tick(在onTick()回调中)它不会更新mapview,我认为这种方法会执行mapView.getController().zoomToSpan((int)latSpan, (int)lonSpan);。现在看起来像是手机暂停了5秒钟,然后缩放到最后一级。有什么想法吗? - per_jansson
1
哦,该死的,我打赌zoomToSpan会启动自己的动画...那真的很烦人。非常抱歉。如果你能立即设置一个浮点缩放级别,它就可以工作...谷歌地图类有多么薄弱,这很奇怪。 - Reuben Scratton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接