Как я могу определить, был ли Android MapView панорамирован или увеличен? - PullRequest
19 голосов
/ 24 февраля 2010

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

Ответы [ 6 ]

4 голосов
/ 24 марта 2011

попробуйте mapview-overlay-manager, это расширение для оверлея для карт Android,

он имеет несколько упрощенных OnGestureListener, несколько примеров:

onSingleTap(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem)

onDoubleTap(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem)

onLongPress(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem)

onZoom(ZoomEvent, ManagedOverlay)

onScrolled(...)

ссылка: http://code.google.com/p/mapview-overlay-manager/ надеюсь, что это поможет

3 голосов
/ 02 марта 2012

Вы можете создать SimpleMapView, который расширяет MapView.

public class SimpleMapView extends MapView {

    private int currentZoomLevel = -1;
    private GeoPoint currentCenter;
    private List<ZoomChangeListener> zoomEvents = new ArrayList<ZoomChangeListener>();
    private List<PanChangeListener> panEvents = new ArrayList<PanChangeListener>();

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

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

    public SimpleMapView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    /**
     * 
     * @return
     */
    public int[][] getBounds() {

        GeoPoint center = getMapCenter();
        int latitudeSpan = getLatitudeSpan();
        int longtitudeSpan = getLongitudeSpan();
        int[][] bounds = new int[2][2];

        bounds[0][0] = center.getLatitudeE6() - (latitudeSpan / 2);
        bounds[0][1] = center.getLongitudeE6() - (longtitudeSpan / 2);

        bounds[1][0] = center.getLatitudeE6() + (latitudeSpan / 2);
        bounds[1][1] = center.getLongitudeE6() + (longtitudeSpan / 2);
        return bounds;
    }

    public boolean onTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_UP) {
            GeoPoint centerGeoPoint = this.getMapCenter();
            if (currentCenter == null || 
                    (currentCenter.getLatitudeE6() != centerGeoPoint.getLatitudeE6()) ||
                    (currentCenter.getLongitudeE6() != centerGeoPoint.getLongitudeE6()) ) {
                firePanEvent(currentCenter, this.getMapCenter());
            }
            currentCenter = this.getMapCenter();
        }
        return super.onTouchEvent(ev);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if(getZoomLevel() != currentZoomLevel){
            fireZoomLevel(currentZoomLevel, getZoomLevel());
            currentZoomLevel = getZoomLevel();
        }
    }

    @Override
    public void setSatellite(boolean on){
        super.setSatellite(on);
    }

    @Override
    public MapController getController(){
        return super.getController();
    }

    private void fireZoomLevel(int old, int current){
        for(ZoomChangeListener event : zoomEvents){
            event.onZoom(old, current);
        }
    }

    private void firePanEvent(GeoPoint old, GeoPoint current){
        for(PanChangeListener event : panEvents){
            event.onPan(old, current);
        }
    }

    public void addZoomChangeListener(ZoomChangeListener listener){
        this.zoomEvents.add(listener);
    }

    public void addPanChangeListener(PanChangeListener listener){
        this.panEvents.add(listener);
    }
}

У вас есть Слушатели, вы можете поставить код для панорамирования или масштабирования. Тогда в вашем xml:

 <com.androidnatic.maps.SimpleMapView android:clickable="true" 
                    android:layout_height="match_parent" android:id="@+id/mapView" 
                    android:layout_width="match_parent"
                     android:apiKey="xxx">
 </com.androidnatic.maps.SimpleMapView>

И тогда в своем коде вы можете указать Pan Listener:

mapView.addPanChangeListener(new PanChangeListener() {

            @Override
            public void onPan(GeoPoint old, GeoPoint current) {
                          //TODO
                        }
        });
1 голос
/ 13 октября 2011

Класс MapView может отслеживать изменения, используя метод onLayout.

т.е.

class CustomMapView extends MapView {

    protected void onLayout(boolean changed,int left, int right, int top, int bottom){
        super.onLayout(changed,left, right, top, bottom);
        if(changed){
        // do something special
        }
    }
}
1 голос
/ 14 июля 2011

К сожалению, в инструментах MapView нет встроенной функциональности для этого (странный недосмотр, поскольку эта функция есть в JavaScript SDK, а также в iOS SDK).

Вы можете справиться с этим достаточно легко, используя Runnable и просто опрашивая MapView. Я делаю это, отслеживая «последнее» состояние:

getLatitudeSpan();
getLongitudeSpan();
getCenter();
getZoomLevel();

А затем сравнивает их с текущими значениями. Если значения изменились, вы знаете, что вид карты сместился. Если нет, вы ничего не можете сделать.

В любом случае, перепланируйте работоспособность для следующего запуска через 500 мс или около того и повторите процесс. Вы можете использовать onResume () и onPause (), чтобы удалить обратный вызов для Runnable и перезапустить его при необходимости.

0 голосов
/ 07 февраля 2014

Старый вопрос, но некоторое время назад я написал класс с именем ExMapView, который генерирует событие, когда регион карты начинает изменяться (onRegionBeginChange) и когда он прекращает изменяться (onRegionEndChange). Этот класс предназначен для использования со старым MapView, а не V2.0. Надеюсь, это кому-нибудь поможет.

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);
    }
}
0 голосов
/ 24 февраля 2010

Единственный способ, который я могу придумать, - это расширить MapView и переопределить OnTouchEvent и наблюдать за действием Up.Это скажет вам, что пользователь закончил перемещение, и вы можете получить широту / долготу, чтобы определить регион, который вы должны проверить.

...