web-dev-qa-db-fra.com

Événement Zoom sur Google Maps sur android

Nous créons une application qui utilise l'API Google Maps pour Android.

J'ai mon MapController et MapView, et j'active les commandes de zoom intégrées en utilisant:

mapView.setBuiltInZoomControls(true);

J'aimerais maintenant obtenir un événement lorsque l'utilisateur fait un zoom sur la carte, comment dois-je procéder? Je ne trouve aucun événement de ce type ni aucun événement général où je puisse détecter un changement de niveau de zoom.

Mise à jour

Le mapView.getZoomControls () est déconseillé . Et la documentation suggère d'utiliser à la place mapView.setBuiltInZoomControls (bool). C'est correct, mais je ne peux tout simplement pas comprendre comment agir sur les événements à partir des commandes de zoom intégrées.

41

Avec Google Maps Android API v2, vous pouvez utiliser un GoogleMap.OnCameraChangeListener comme ceci:

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

Vous pouvez implémenter votre propre "interrogation" de base de la valeur du zoom pour détecter quand le zoom a été modifié en utilisant le Android Gestionnaire .

Utilisation du code suivant pour votre événement exécutable . C'est là que votre traitement doit être effectué.

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

Démarrer un événement de rappel en utilisant

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

et l'arrêter lorsque vous quittez l'activité en utilisant

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

Article sur lequel il est basé peut être trouvé ici si vous voulez une écriture plus longue.

25
Kurru

J'utilise cette bibliothèque qui a un écouteur de fonction onZoom. http://code.google.com/p/mapview-overlay-manager/ . Fonctionne bien.

7
Abhinav

Comme l'OP l'a dit, utilisez l'événement onUserInteractionEvent et faites le test vous-même.

5
Billy Bob Bain

Voici une solution propre. Ajoutez simplement cette classe privée TouchOverlay à votre activité et une méthode appelée onZoom (qui est appelée par cette classe interne).

Remarque, vous devrez ajouter ce TouchOverlay à votre mapView, par ex.

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

Il garde une trace du niveau de zoom chaque fois que l'utilisateur touche la carte, par ex. pour appuyer deux fois ou pincer le zoom, puis déclenche la méthode onZoom (avec le niveau de zoom) si le niveau de zoom change.

   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
        }
5
Damian

Vous pouvez utiliser

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

j'espère que ça aide

4
Felipe Conde

API Android vous suggère d'utiliser ZoomControls qui a un setOnZoomInClickListener ()

Pour ajouter ces commandes de zoom, vous devez:

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

Et puis ajoutez mZoom à votre mise en page.

4
JasonOfEarth

Je pense qu'il pourrait y avoir une autre réponse à cette question. La méthode de dessin de la classe Overlay est appelée après tout zoom et je crois que cela est appelé après les changements de niveau de zoom. Ne pourriez-vous pas concevoir votre application pour en profiter? Vous pouvez même utiliser une superposition factice juste pour détecter cela si vous le souhaitez. Ne serait-ce pas plus efficace que d'utiliser un exécutable avec un retard?

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

Pour la pré-V2.0, j'ai créé une classe qui étend MapView qui alerte un écouteur avec des événements lorsque la région de la carte commence à changer (onRegionBeginChange) et cesse de changer (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);
    }
}
2
David

U peut avoir Zoom CControl comme ça.

Ici, j'attache du code comment vous pouvez implémenter zoomcontrol.

1 >> Le fichier XML devrait ressembler à ceci.

<?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 >> Sur votre activité principale dans la méthode oncreate, faites les choses suivantes. ici vous gonflez votre vue avec 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);

.................................................. ......... Voici comment vous pouvez utiliser le contrôle de zoom intégré de l'API ..

Vous pouvez avoir votre propre code personnalisé pour implémenter le zoom avant et le zoom arrière comme ceci ...

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

..C'est ainsi que j'ai mis en œuvre ...

Merci..Rakesh

2
Rakesh Gondaliya

J'ai utilisé un mélange de ce qui précède. J'ai trouvé qu'en utilisant le timmer pour démarrer un thread toutes les demi-secondes, la carte était vraiment jenky. Probablement parce que j'utilisais à chaque fois quelques relevés If. J'ai donc commencé le fil sur un délai de post de 500 ms à partir de onUserInteraction. Cela donne suffisamment de temps pour que zoomLevel se mette à jour avant que le thread ne démarre, obtenant ainsi le niveau de zoom correct sans exécuter un thread toutes les 500 ms.

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