42

我们正在构建一个使用 google maps api for android 的应用程序。

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

mapView.setBuiltInZoomControls(true);

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

更新

mapView.getZoomControls() 已弃用。并且文档建议改用 mapView.setBuiltInZoomControls(bool) 。这没关系,但我根本无法弄清楚如何对内置缩放控件的事件采取行动。

4

11 回答 11

40

使用 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
        }
    }
});
于 2013-02-23T23:04:01.723 回答
25

您可以使用 android Handler实现自己的基本“轮询”缩放值,以检测缩放何时更改。

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

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
}

如果您想写更长的文章,可以在此处找到本文所依据的文章。

于 2011-03-17T21:05:13.270 回答
7

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

于 2011-03-16T11:50:51.870 回答
5

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

于 2010-01-07T01:08:56.807 回答
5

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

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

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
        }
于 2012-05-14T13:55:41.257 回答
4

android API建议您使用具有 setOnZoomInClickListener()的ZoomControls

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

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

然后将 mZoom 添加到您的布局中。

于 2010-01-06T14:36:53.767 回答
4

您可以使用

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

希望能帮助到你

于 2010-06-23T01:04:37.307 回答
3

我认为这个问题可能还有另一个答案。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);
}
于 2012-03-17T16:19:49.650 回答
2

你可以像这样拥有 Zoom CControl。

在这里,我附上了如何实现缩放控制的代码。

1>> XML 文件应该是这样的。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent">

    <com.google.android.maps.MapView 
        android:id="@+id/mapView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:enabled="true"
        android:clickable="true"
        android:apiKey="0l4sCTTyRmXTNo7k8DREHvEaLar2UmHGwnhZVHQ"
        />

    <LinearLayout android:id="@+id/zoom" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_alignParentBottom="true" 
        android:layout_centerHorizontal="true" 
        /> 

</RelativeLayout>

2>> 在 oncreate 方法中的主要活动上做以下事情。在这里,您正在使用 mapView 膨胀您的视图

mapView = (MapView) findViewById(R.id.mapView);
        LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom);  
        View zoomView = mapView.getZoomControls(); 

        zoomLayout.addView(zoomView, 
            new LinearLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, 
                LayoutParams.WRAP_CONTENT)); 
        mapView.displayZoomControls(true);

..................................................... ......... 这就是您可以使用 API 的内置缩放控制的方式。

您可以拥有自己的自定义代码来实现像这样的放大和缩小...

public boolean onKeyDown(int keyCode, KeyEvent event) 
{
    MapController mc = mapView.getController(); 
    switch (keyCode) 
    {
        case KeyEvent.KEYCODE_3:
            mc.zoomIn();
            break;
        case KeyEvent.KEYCODE_1:
            mc.zoomOut();
            break;
    }
    return super.onKeyDown(keyCode, event);
}    

..这就是我实施的方式...

谢谢..拉克什

于 2010-08-27T10:55:29.360 回答
2

对于 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);
    }
}
于 2014-02-07T04:15:25.147 回答
1

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

public void onUserInteraction() {
    handler.postDelayed(zoomChecker, zoomCheckingDelay);
}
于 2011-04-29T12:48:05.083 回答