bobetko
bobetko

Reputation: 5167

How to implemennt OnZoomListener on MapView

I would like to have onZoomListener on my MapView. The code below is what I have done. It registers if zoom buttons are tapped. Since all new phones now supports pinch to zoom, this is useless. Does anybody have idea how to do real onZoomListener? Thanks.

   OnZoomListener listener = new OnZoomListener() {
   @Override
   public void onVisibilityChanged(boolean arg0) {
    // TODO Auto-generated method stub

   }
   @Override
   public void onZoom(boolean arg0) {
    Log.d(TAG, "ZOOM CHANGED");
    // TODO Auto-generated method stub

   }
  };

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

Upvotes: 10

Views: 12208

Answers (8)

Try via this method

map.setMapListener(new MapListener()
                {
                    ....

                    @Override
                    public boolean onZoom(ZoomEvent event)
                        {

                            return false;
                        }
                });

Upvotes: 1

rDroid
rDroid

Reputation: 4945

i implemented it the following way, and it works for single/multitouch :

@Override
protected void dispatchDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.dispatchDraw(canvas);
    if (oldZoomLevel == -1) {
        oldZoomLevel = getZoomLevel();
    }
    if (oldZoomLevel < getZoomLevel()) {
        System.out.println("zoomed in");
        if (mOnZoomInListener != null) {
            mOnZoomInListener
                    .onZoomedIn(this, oldZoomLevel, getZoomLevel());
        }
    }
    if (oldZoomLevel > getZoomLevel()) {
        System.out.println("zoomed out");
        if (mOnZoomOutListener != null) {
            mOnZoomOutListener.onZoomedOut(this, oldZoomLevel,
                    getZoomLevel());
        }
    }

It worked for me!

Upvotes: 0

rDroid
rDroid

Reputation: 4945

use dispatchTouch() method to detect touch events on the map and make sure you call the super() method to carry out the default map touch functions. (Setting onTouchListener will disable the in built events like zooming and panning if you return true from your functiion, and will handle touch only once if you return false.)

in dispatchTouch method, you can check for no of touch points by using event.getPointerCount(). use Action_UP to detect whether the user has zoomed out or not by calling mapview.getZoomLevel(); if you find the zoom level changed, you can carry out your actions.

Upvotes: 0

Cliff
Cliff

Reputation: 11

Maybe a bit late, but have you tried with an OnOverlayGestureListener?

http://code.google.com/p/mapview-overlay-manager/wiki/OnOverlayGestureListener

Upvotes: 1

vinzenzweber
vinzenzweber

Reputation: 3389

I put all the code from above together and came up with this class:


package at.blockhaus.wheels.map;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;

public class CustomMapView extends MapView {

    private int oldZoomLevel = -1;
    private GeoPoint oldCenterGeoPoint;
    private OnPanAndZoomListener mListener;

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

    public CustomMapView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    public void setOnPanListener(OnPanAndZoomListener listener) {
        mListener = listener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_UP) {
            GeoPoint centerGeoPoint = this.getMapCenter();
            if (oldCenterGeoPoint == null || 
                    (oldCenterGeoPoint.getLatitudeE6() != centerGeoPoint.getLatitudeE6()) ||
                    (oldCenterGeoPoint.getLongitudeE6() != centerGeoPoint.getLongitudeE6()) ) {
                mListener.onPan();
            }
            oldCenterGeoPoint = this.getMapCenter();
        }
        return super.onTouchEvent(ev);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if (getZoomLevel() != oldZoomLevel) {
            mListener.onZoom();
            oldZoomLevel = getZoomLevel();
        }
    }


}

And the corresponding listener interface:


package at.blockhaus.wheels.map;

public interface OnPanAndZoomListener {
    public void onPan();
    public void onZoom();
}

Upvotes: 11

bobetko
bobetko

Reputation: 5167

I had to subclass MapView and override dispatchDraw

Here is the code:

 int oldZoomLevel=-1;
 @Override
 public void dispatchDraw(Canvas canvas) {
  super.dispatchDraw(canvas);
  if (getZoomLevel() != oldZoomLevel) {
   Log.d(TAG, "ZOOOMED");
   oldZoomLevel = getZoomLevel();
  }
 }

This blog helped me a lot: http://pa.rezendi.com/2010/03/responding-to-zooms-and-pans-in.html

Above works great. Is there maybe simpler solution? I tried to implement onTouchListener on MapView directly but touch event would be detected only once if onTouchListener would return false. If it would return true, touch would be detected every time, but map zooming and panning wouldn't work.

Upvotes: 26

Nick Campion
Nick Campion

Reputation: 10479

Edit: I believe what you've found is probably the only mechanism to allow this detection. (Editing my post to remove misinformation) Extending the MapView and overriding the onDraw() method would work. One consideration to make will be how often to fire the code listening to zoom. For instance, while zooming the onDraw may be called dozens of times each with a different zoom level. This may cause poor performance if your listener is firing every time. You could throttle this by determining that a zoom change has taken place and then waiting for the zoom level to be the same on two subsequent redraws before firing the event. This all depends on how you want your code to be called.

Upvotes: 0

ShadowMare
ShadowMare

Reputation: 2097

MapView provides build-in zoom controls that support pinch. If it doesn't work out of the box you could try setting mapView.setBuiltInZoomControls(true); This way you should not need the OnZoomListener.

Upvotes: -7

Related Questions