Android 上谷歌地图的缩放事件

发布于 2024-08-16 23:28:30 字数 525 浏览 6 评论 0原文

我们正在构建一个使用 Android 版谷歌地图 API 的应用程序。

我有我的 MapController 和 MapView,并且我使用以下方式启用内置缩放控件:

mapView.setBuiltInZoomControls(true);

我现在想在用户实际缩放地图时收到一个事件,我该怎么做?我找不到这样的事件或任何可以检测到缩放级别变化的一般事件。

更新

mapView.getZoomControls() 已弃用。文档建议使用 mapView.setBuiltInZoomControls(bool) 代替。这没关系,但我根本不知道如何对内置缩放控件中的事件采取行动。

We're building an application which is using the google maps api for android.

I have my MapController and MapView, and I enable the built-in zoom controls using:

mapView.setBuiltInZoomControls(true);

I would now like to get an event when the user actually zooms on the map, how do I go about that? I can find no such event or any general event where I could detect a change in zoom level.

Update

The mapView.getZoomControls() is deprecated. And the documentation suggests using mapView.setBuiltInZoomControls(bool) instead. This is okay, but I simply cannot figure out how to act on events from the built in zoom controls.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

落花随流水 2024-08-23 23:28:30

通过 Google Maps Android API v2,您可以使用 GoogleMap.OnCameraChangeListener 像这样:

mMap.setOnCameraChangeListener(new OnCameraChangeListener() {

    private float currentZoom = -1;

    @Override
    public void onCameraChange(CameraPosition pos) {
        if (pos.zoom != currentZoom){
            currentZoom = pos.zoom;
            // do you action here
        }
    }
});

With the Google Maps Android API v2 you can use a GoogleMap.OnCameraChangeListener like this:

mMap.setOnCameraChangeListener(new OnCameraChangeListener() {

    private float currentZoom = -1;

    @Override
    public void onCameraChange(CameraPosition pos) {
        if (pos.zoom != currentZoom){
            currentZoom = pos.zoom;
            // do you action here
        }
    }
});
不交电费瞎发啥光 2024-08-23 23:28:30

您可以使用 android 处理程序

将以下代码用于您的可运行事件。这是您应该进行处理的地方。

private Handler handler = new Handler();

public static final int zoomCheckingDelay = 500; // in ms

private Runnable zoomChecker = new Runnable()
{
    public void run()
    {
        checkMapIcons();

        handler.removeCallbacks(zoomChecker); // remove the old callback
        handler.postDelayed(zoomChecker, zoomCheckingDelay); // register a new one
    }
};

使用启动回调事件

protected void onResume()
{
    super.onResume();
    handler.postDelayed(zoomChecker, zoomCheckingDelay);
}

,并在您离开活动时使用

protected void onPause()
{
    super.onPause();
    handler.removeCallbacks(zoomChecker); // stop the map from updating
}

文章停止回调事件,该事件基于这里如果你想写更长的文章。

You can implement your own basic "polling" of the zoom value to detect when the zoom has been changed using the android Handler.

Using the following code for your runnable event. This is where your processing should be done.

private Handler handler = new Handler();

public static final int zoomCheckingDelay = 500; // in ms

private Runnable zoomChecker = new Runnable()
{
    public void run()
    {
        checkMapIcons();

        handler.removeCallbacks(zoomChecker); // remove the old callback
        handler.postDelayed(zoomChecker, zoomCheckingDelay); // register a new one
    }
};

Start a callback event using

protected void onResume()
{
    super.onResume();
    handler.postDelayed(zoomChecker, zoomCheckingDelay);
}

and stop it when you're leaving the activity using

protected void onPause()
{
    super.onPause();
    handler.removeCallbacks(zoomChecker); // stop the map from updating
}

Article this is based on can be found here if you want a longer write up.

月亮是我掰弯的 2024-08-23 23:28:30

我使用这个具有 onZoom 函数侦听器的库。 http://code.google.com/p/mapview-overlay-manager/。效果很好。

I use this library which has an onZoom function listener. http://code.google.com/p/mapview-overlay-manager/. Works well.

春夜浅 2024-08-23 23:28:30

正如OP所说,使用onUserInteractionEvent并自己进行测试。

As the OP said, use the onUserInteractionEvent and do the test yourself.

划一舟意中人 2024-08-23 23:28:30

这是一个干净的解决方案。只需将此 TouchOverlay 私有类添加到您的 Activity 中,并添加一个名为 onZoom 的方法(由该内部类调用)。

请注意,您必须将此 TouchOverlay 添加到您的地图视图中,例如,

mapView.getOverlays().add(new TouchOverlay());

每当用户触摸地图(例如双击或捏缩放)时,它都会跟踪缩放级别,然后在缩放时触发 onZoom 方法(使用缩放级别)水平变化。

   private class TouchOverlay extends com.google.android.maps.Overlay {
            int lastZoomLevel = -1;

            @Override
            public boolean onTouchEvent(MotionEvent event, MapView mapview) {
                if (event.getAction() == 1) {
                    if (lastZoomLevel == -1)
                        lastZoomLevel = mapView.getZoomLevel();

                    if (mapView.getZoomLevel() != lastZoomLevel) {
                        onZoom(mapView.getZoomLevel());
                        lastZoomLevel = mapView.getZoomLevel();
                    }
                }
                return false;
            }
        }

        public void onZoom(int level) {
            reloadMapData(); //act on zoom level change event here
        }

Here is a clean solution. Simply add this TouchOverlay private class to your activity and a method called onZoom (that is called by this inner class).

Note, you'll have to add this TouchOverlay to your mapView e.g.

mapView.getOverlays().add(new TouchOverlay());

It keeps track of the zoom level whenever the user touches the map e.g. to double-tap or pinch zoom and then fires the onZoom method (with the zoom level) if the zoom level changes.

   private class TouchOverlay extends com.google.android.maps.Overlay {
            int lastZoomLevel = -1;

            @Override
            public boolean onTouchEvent(MotionEvent event, MapView mapview) {
                if (event.getAction() == 1) {
                    if (lastZoomLevel == -1)
                        lastZoomLevel = mapView.getZoomLevel();

                    if (mapView.getZoomLevel() != lastZoomLevel) {
                        onZoom(mapView.getZoomLevel());
                        lastZoomLevel = mapView.getZoomLevel();
                    }
                }
                return false;
            }
        }

        public void onZoom(int level) {
            reloadMapData(); //act on zoom level change event here
        }
流年里的时光 2024-08-23 23:28:30

android API 建议您使用 ZoomControls ,它有一个 setOnZoomInClickListener()

要添加这些缩放控件,您需要:

ZoomControls mZoom = (ZoomControls) mapView.getZoomControls();

然后将 mZoom 添加到你的布局。

The android API suggests you use ZoomControls which has a setOnZoomInClickListener()

To add these zoom controls you would:

ZoomControls mZoom = (ZoomControls) mapView.getZoomControls();

And then add mZoom to your layout.

想挽留 2024-08-23 23:28:30

你可以使用

ZoomButtonsController zoomButton = mapView.getZoomButtonsController();
zoomButton.setOnZoomListener(listener);

希望它有帮助

You Can use

ZoomButtonsController zoomButton = mapView.getZoomButtonsController();
zoomButton.setOnZoomListener(listener);

hope it helps

木格 2024-08-23 23:28:30

我想这个问题可能还有另一个答案。 Overlay 类绘制方法在任何缩放后调用,我相信这是在缩放级别更改后调用的。您不能设计您的应用程序来利用这一点吗?如果您愿意,您甚至可以使用虚拟覆盖层来检测这一点。这不是比使用带有延迟的可运行程序更有效吗?

@Override
public boolean draw (Canvas canvas, MapView mapView, boolean shadow, long when) {
    int zoomLevel = mapView.getZoomLevel();
    // do what you want with the zoom level
    return super.draw(canvas, mapView, shadow, when);
}

I think there might another answer to this question. The Overlay class draw method is called after any zoom and I believe this is called after the zoom level changes. Could you not architect your app to take advantage of this? You could even use a dummy overlay just to detect this if you wanted to. Would this not be more efficient than using a runnable with a delay?

@Override
public boolean draw (Canvas canvas, MapView mapView, boolean shadow, long when) {
    int zoomLevel = mapView.getZoomLevel();
    // do what you want with the zoom level
    return super.draw(canvas, mapView, shadow, when);
}
忆梦 2024-08-23 23:28:30

对于 V2.0 之前的版本,我创建了一个扩展 MapView 的类,当地图区域开始更改 (onRegionBeginChange) 和停止更改 (onRegionEndChange) 时,该类会向侦听器发出事件警报。

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;

public class ExMapView extends MapView {
    private static final String TAG = ExMapView.class.getSimpleName();
    private static final int DURATION_DEFAULT = 700;

    private OnRegionChangedListener onRegionChangedListener;
    private GeoPoint previousMapCenter;
    private int previousZoomLevel;
    private int changeDuration; // This is the duration between when the user stops moving the map around and when the onRegionEndChange event fires.
    private boolean isTouched = false;
    private boolean regionChanging = false;

    private Runnable onRegionEndChangeTask = new Runnable() {
        public void run() {
            regionChanging = false;
            previousMapCenter = getMapCenter();
            previousZoomLevel = getZoomLevel();
            if (onRegionChangedListener != null) {
                onRegionChangedListener.onRegionEndChange(ExMapView.this, previousMapCenter, previousZoomLevel);
            }
        }
    };

    public ExMapView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ExMapView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public ExMapView(Context context, String apiKey) {
        super(context, apiKey);
        init();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        isTouched = event.getAction() != MotionEvent.ACTION_UP;
        return super.onTouchEvent(event);
    }

    @Override
    public void computeScroll() {
        super.computeScroll();

        // If the map region is still changing (user is still scrolling or zooming), reset timer for onRegionEndChange.
        if ((!isTouched && !getMapCenter().equals(previousMapCenter)) || (previousZoomLevel != getZoomLevel())) {

            // If the region has just begun changing, fire off onRegionBeginChange event.
            if (!regionChanging) {
                regionChanging = true;
                if (onRegionChangedListener != null) {
                    onRegionChangedListener.onRegionBeginChange(this, previousMapCenter, previousZoomLevel);
                }
            }

            // Reset timer for onRegionEndChange.
            removeCallbacks(onRegionEndChangeTask);
            postDelayed(onRegionEndChangeTask, changeDuration);
        }
    }

    private void init() {
        changeDuration = DURATION_DEFAULT;
        previousMapCenter = getMapCenter();
        previousZoomLevel = getZoomLevel();
    }

    public void setOnRegionChangedListener(OnRegionChangedListener listener) {
        onRegionChangedListener = listener;
    }

    public void setChangeDuration(int duration) {
        changeDuration = duration;
    }

    public interface OnRegionChangedListener {
        public abstract void onRegionBeginChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel);
        public abstract void onRegionEndChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel);
    }
}

For pre-V2.0, I made a class which extends MapView that alerts a listener with events when the map region starts changing (onRegionBeginChange) and stops changing (onRegionEndChange).

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;

public class ExMapView extends MapView {
    private static final String TAG = ExMapView.class.getSimpleName();
    private static final int DURATION_DEFAULT = 700;

    private OnRegionChangedListener onRegionChangedListener;
    private GeoPoint previousMapCenter;
    private int previousZoomLevel;
    private int changeDuration; // This is the duration between when the user stops moving the map around and when the onRegionEndChange event fires.
    private boolean isTouched = false;
    private boolean regionChanging = false;

    private Runnable onRegionEndChangeTask = new Runnable() {
        public void run() {
            regionChanging = false;
            previousMapCenter = getMapCenter();
            previousZoomLevel = getZoomLevel();
            if (onRegionChangedListener != null) {
                onRegionChangedListener.onRegionEndChange(ExMapView.this, previousMapCenter, previousZoomLevel);
            }
        }
    };

    public ExMapView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ExMapView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public ExMapView(Context context, String apiKey) {
        super(context, apiKey);
        init();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        isTouched = event.getAction() != MotionEvent.ACTION_UP;
        return super.onTouchEvent(event);
    }

    @Override
    public void computeScroll() {
        super.computeScroll();

        // If the map region is still changing (user is still scrolling or zooming), reset timer for onRegionEndChange.
        if ((!isTouched && !getMapCenter().equals(previousMapCenter)) || (previousZoomLevel != getZoomLevel())) {

            // If the region has just begun changing, fire off onRegionBeginChange event.
            if (!regionChanging) {
                regionChanging = true;
                if (onRegionChangedListener != null) {
                    onRegionChangedListener.onRegionBeginChange(this, previousMapCenter, previousZoomLevel);
                }
            }

            // Reset timer for onRegionEndChange.
            removeCallbacks(onRegionEndChangeTask);
            postDelayed(onRegionEndChangeTask, changeDuration);
        }
    }

    private void init() {
        changeDuration = DURATION_DEFAULT;
        previousMapCenter = getMapCenter();
        previousZoomLevel = getZoomLevel();
    }

    public void setOnRegionChangedListener(OnRegionChangedListener listener) {
        onRegionChangedListener = listener;
    }

    public void setChangeDuration(int duration) {
        changeDuration = duration;
    }

    public interface OnRegionChangedListener {
        public abstract void onRegionBeginChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel);
        public abstract void onRegionEndChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel);
    }
}
谷夏 2024-08-23 23:28:30

我使用了上述的混合物。我发现使用计时器每半秒启动一个线程会导致地图变得非常不稳定。可能是因为我每次都使用几个 If 语句。因此,我在 onUserInteraction 后延迟 500 毫秒后启动了该线程。这为在线程开始运行之前更新 ZoomLevel 提供了足够的时间,从而无需每 500 毫秒运行一个线程即可获得正确的缩放级别。

public void onUserInteraction() {
    handler.postDelayed(zoomChecker, zoomCheckingDelay);
}

I used a mixture of the above. I found that using the timmer to start a thread every half a second cause the map to be really jenky. Probably because I was using a couple of If statments everytime. So I started the thread on a post delay of 500ms from the onUserInteraction. This gives enough time for the zoomLevel to update before the thread starts to run thus getting the correct zoomlevel without running a thread every 500ms.

public void onUserInteraction() {
    handler.postDelayed(zoomChecker, zoomCheckingDelay);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文