Java android上谷歌地图的缩放事件

Java android上谷歌地图的缩放事件,java,android,events,google-maps,zooming,Java,Android,Events,Google Maps,Zooming,我们正在构建一个应用程序,该应用程序使用android的谷歌地图api 我有我的MapController和MapView,我使用以下方式启用内置的缩放控件: mapView.setBuiltInZoomControls(true); 我现在想得到一个事件,当用户实际缩放地图时,我该怎么做?我找不到这样的事件或任何可以检测到缩放级别变化的一般事件 更新 。文档建议使用mapView.SetBuilTinZoomControl(bool)。这没关系,但我根本不知道如何处理内置缩放控件中的事件。建

我们正在构建一个应用程序,该应用程序使用android的谷歌地图api

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

mapView.setBuiltInZoomControls(true);
我现在想得到一个事件,当用户实际缩放地图时,我该怎么做?我找不到这样的事件或任何可以检测到缩放级别变化的一般事件

更新

。文档建议使用mapView.SetBuilTinZoomControl(bool)。这没关系,但我根本不知道如何处理内置缩放控件中的事件。

建议您使用带有setOnZoomInClickListener()的

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

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

然后将mZoom添加到布局中。

如操作所述,使用onUserInteractionEvent并自己进行测试。

您可以使用

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

希望对您有所帮助

您可以像这样进行缩放控制

<?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>
这里我附上代码如何实现zoomcontrol

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>
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 这就是如何使用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);
}    
…我就是这样实施的


谢谢..Rakesh

我使用这个库,它有一个onZoom函数侦听器。工作正常。

您可以实现自己的缩放值基本“轮询”,以检测何时使用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
}

文章如果你想写更长的文章,可以找到这篇文章。

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

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

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

@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);
}

这是一个干净的解决方案。只需将这个TouchOverlay私有类添加到您的活动和一个名为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
        }

使用Google Maps Android API v2,您可以使用类似的:

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
        }
    }
});

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


谢谢你的回答。不推荐使用MapView.GetZoomControl(),建议使用MapView.SetBuilTinZoomControl(布尔)方法。但是我找不到任何地方可以从这些内置的缩放控件中获取任何事件。我明白了。看起来您可以使用一个未记录的mapView.getZoomButtonsController(),如中所述,否则您只需使用mapView.onkeydown并对缩放进行测试。我通过使用onUserInteraction事件和手动测试缩放级别的更改获得了想要的结果。如果有一条toast消息通知用户有必要放大以查看我的覆盖图,它的效果非常好。出于同样的目的,我尝试实现onUserInteraction事件,但仍然存在问题。我正在显示一个需要根据缩放级别进行缩放的图像,因此很明显,当用户缩放时,我想调用它的redraw()方法。我的问题是,当用户单击缩放按钮时,会调用onUserInteraction,因此zoomLevel尚未更新,只有在下一次交互(单击、跨距等)时,zoomLevel才会更新。因此,我的图像仅在实际缩放后的交互后更新。有什么想法吗?这个问题和答案是关于API v1的,我在下面添加了一个新的答案,说明在缩放级别更改之前调用了
onUserInteractionEvent()
。这实际上意味着,对于每个缩放事件,监控缩放的应用程序都会落后一个事件。@Paul:Hi。最初我没有考虑这个问题,但似乎你是对的,我所展示的敬酒永远是一个甚至落后。你可以创建一个<代码>汉德勒<代码>实例,并通过诸如<代码>延迟(新的Runnable)({…},500)< /代码>定期检查缩放级别的变化,但我真的不喜欢这种解决方案。我对这个答案给予了奖励,因为这是确定地图是否已被移动或缩放的最简单方法。这非常明确地回答了OP的问题,但只通过缩放按钮引发缩放事件。例如,Pinching不会调用侦听器的回调。听起来很有希望。我会仔细看看!使用您的解决方案,我能够轻松捕获缩放更改!ThxBrilliant解决方案,但是它没有检测到变焦的第一次变化。删除-1的第一个if语句修复了这一问题。
setOnCameraChangeListener()
现在已被弃用
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);
    }
}