Событие масштабирования для карт google на Android

Мы создаем приложение, использующее Google Maps api для Android.

У меня есть MapController и MapView, и я включаю встроенные элементы управления увеличением, используя:

mapView.setBuiltInZoomControls(true);

Теперь я хотел бы получить событие, когда пользователь действительно масштабирует карту, как мне это сделать? Я не могу найти такого события или какого-либо общего события, где я мог бы обнаружить изменение уровня масштабирования.

Обновление

Функция mapView.getZoomControls() устарела. И в документации предлагается использовать mapView.setBuiltInZoomControls(bool). Это нормально, но я просто не могу понять, как действовать на события из встроенных средств управления увеличением.

Ответ 1

В Google API Android Android 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
        }
    }
});

Ответ 2

Вы можете реализовать свой собственный "опрос" значения масштабирования, чтобы определить, когда масштаб был изменен с помощью андроида 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
}

Статья основана на том, что вы можете найти здесь, если вам нужна более длинная запись.

Ответ 4

Как сказал OP, используйте onUserInteractionEvent и выполните тест самостоятельно.

Ответ 5

API Android предлагает вам ZoomControls, который имеет setOnZoomInClickListener()

Чтобы добавить эти элементы управления увеличением, вы должны:

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

Затем добавьте mZoom в свой макет.

Ответ 6

Вы можете использовать

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

надеюсь, что это поможет

Ответ 7

Вот чистое решение. Просто добавьте этот частный класс 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
        }

Ответ 8

Я думаю, что на этот вопрос может быть и другой ответ. Метод рисования класса Overlay вызывается после любого увеличения, и я считаю, что это вызвано после изменения уровня масштабирования. Могли бы вы не архивировать приложение, чтобы воспользоваться этим? Вы даже можете использовать фиктивный оверлей, чтобы обнаружить это, если хотите. Не будет ли это более эффективным, чем использование 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);
}

Ответ 9

U может иметь Zoom CControl, как это.

Здесь я прикрепляю код, как вы можете реализовать 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>

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..

У вас может быть свой собственный код для реализации Zoom In And Zoom, как это...

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

.. Вот как я реализовал...

Thanks..Rakesh

Ответ 10

Для pre-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);
    }
}

Ответ 11

Я использовал смесь вышеуказанного. Я обнаружил, что использование timmer для запуска потока каждые полсекунды приводит к тому, что карта будет действительно jenky. Наверное, потому, что я каждый раз использовал пару статусов If. Поэтому я начал поток на задержку сообщения 500 мс из onUserInteraction. Это дает достаточно времени для обновления zoomLevel до того, как поток начнет работать, тем самым получив правильный масштабный уровень без запуска потока каждые 500 мс.

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