Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

On zoom event for google maps on android

We're building an application which is using the google maps api for android.

I have my MapController and MapView, and I enable the built-in zoom controls using:

mapView.setBuiltInZoomControls(true);

I would now like to get an event when the user actually zooms on the map, how do I go about that? I can find no such event or any general event where I could detect a change in zoom level.

Update

The mapView.getZoomControls() is deprecated. And the documentation suggests using mapView.setBuiltInZoomControls(bool) instead. This is okay, but I simply cannot figure out how to act on events from the built in zoom controls.

like image 916
Bjarke Freund-Hansen Avatar asked Jan 06 '10 14:01

Bjarke Freund-Hansen


People also ask

Can you use Google Maps and zoom at the same time?

Google Maps - cannot zoom and move at the same time with animateCamera, but can with moveCamera. Bookmark this question.

How do I add a zoom button to Google Maps?

To navigate, press the arrow keys. Below is a list of the full set of controls you can use in your maps: The Zoom control displays "+" and "-" buttons for changing the zoom level of the map. This control appears by default in the bottom right corner of the map.

How do I fix Google Maps zoom?

To fix Google maps zooming problems, for Google maps default zoom you want to know how to change the zoom level on Google Maps. You can change the zoom level by going to the Edit map page and then selecting 'default zoom level' in the map information section and then clicking save map.


11 Answers

With the Google Maps Android API v2 you can use a GoogleMap.OnCameraChangeListener like this:

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
        }
    }
});
like image 105
tarmelop Avatar answered Sep 22 '22 14:09

tarmelop


You can implement your own basic "polling" of the zoom value to detect when the zoom has been changed using the android Handler.

Using the following code for your runnable event. This is where your processing should be done.

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

Start a callback event using

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

and stop it when you're leaving the activity using

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

Article this is based on can be found here if you want a longer write up.

like image 24
Kurru Avatar answered Sep 21 '22 14:09

Kurru


I use this library which has an onZoom function listener. http://code.google.com/p/mapview-overlay-manager/. Works well.

like image 40
Abhinav Avatar answered Sep 23 '22 14:09

Abhinav


As the OP said, use the onUserInteractionEvent and do the test yourself.

like image 24
Billy Bob Bain Avatar answered Sep 22 '22 14:09

Billy Bob Bain


Here is a clean solution. Simply add this TouchOverlay private class to your activity and a method called onZoom (that is called by this inner class).

Note, you'll have to add this TouchOverlay to your mapView e.g.

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

It keeps track of the zoom level whenever the user touches the map e.g. to double-tap or pinch zoom and then fires the onZoom method (with the zoom level) if the zoom level changes.

   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
        }
like image 45
Damian Avatar answered Sep 22 '22 14:09

Damian


The android API suggests you use ZoomControls which has a setOnZoomInClickListener()

To add these zoom controls you would:

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

And then add mZoom to your layout.

like image 26
JasonOfEarth Avatar answered Sep 21 '22 14:09

JasonOfEarth


You Can use

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

hope it helps

like image 23
Felipe Conde Avatar answered Sep 20 '22 14:09

Felipe Conde


I think there might another answer to this question. The Overlay class draw method is called after any zoom and I believe this is called after the zoom level changes. Could you not architect your app to take advantage of this? You could even use a dummy overlay just to detect this if you wanted to. Would this not be more efficient than using a runnable with a delay?

@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);
}
like image 22
Paul Avatar answered Sep 20 '22 14:09

Paul


U can have Zoom CControl like this.

Here i am attaching code how u can implement zoomcontrol.

1>> XML file should be like this.

<?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>> On you main activity inside oncreate method do following things. here you are inflating your view with 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);

........................................................... This is how you can use inbuilt zoom control of API..

You can have your own custom code to implement Zoom in And Zoom out like this...

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

..This is how i have implemented...

Thanks..Rakesh

like image 33
Rakesh Gondaliya Avatar answered Sep 20 '22 14:09

Rakesh Gondaliya


For pre-V2.0, I made a class which extends MapView that alerts a listener with events when the map region starts changing (onRegionBeginChange) and stops changing (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);
    }
}
like image 20
David Avatar answered Sep 20 '22 14:09

David


I used a mixture of the above. I found that using the timmer to start a thread every half a second cause the map to be really jenky. Probably because I was using a couple of If statments everytime. So I started the thread on a post delay of 500ms from the onUserInteraction. This gives enough time for the zoomLevel to update before the thread starts to run thus getting the correct zoomlevel without running a thread every 500ms.

public void onUserInteraction() {
    handler.postDelayed(zoomChecker, zoomCheckingDelay);
}
like image 31
jiduvah Avatar answered Sep 23 '22 14:09

jiduvah