Как реализовать OnZoomListener на MapView

Я хотел бы иметь onZoomListener на моем MapView. Код ниже - это то, что я сделал. Он регистрирует нажатие кнопок масштабирования. Поскольку все новые телефоны теперь поддерживают щепотку для увеличения, это бесполезно. У кого-нибудь есть идея, как делать реальные onZoomListener? Спасибо.

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

Ответ 1

Мне пришлось подклассировать MapView и переопределить dispatchDraw

Вот код:

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

Этот блог мне очень помог: http://pa.rezendi.com/2010/03/responding-to-zooms-and-pans-in.html

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

Ответ 2

Я поставил весь код сверху вместе и придумал этот класс:


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


}

И соответствующий интерфейс слушателя:


package at.blockhaus.wheels.map;

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

Ответ 4

Изменить: Я считаю, что то, что вы нашли, вероятно, является единственным механизмом, позволяющим это обнаружение. (Редактирование моего сообщения, чтобы удалить дезинформацию). Расширение MapView и переопределение метода onDraw() будут работать. Одним из соображений, которые нужно сделать, будет то, как часто запускать код, прослушивающий масштаб. Например, при масштабировании onDraw можно называть десятки раз с разным уровнем масштабирования. Это может привести к низкой производительности, если ваш слушатель стреляет каждый раз. Вы можете дросселировать это, определив, что произошло изменение масштабирования, а затем ожидание того, что уровень масштабирования будет одинаковым при двух последующих перерисованиях до запуска события. Все зависит от того, как вы хотите, чтобы ваш код вызывался.

Ответ 5

используйте метод dispatchTouch() для обнаружения событий касания на карте и убедитесь, что вы вызываете метод super() для выполнения функций касания карты по умолчанию. (Установка onTouchListener отключит встроенные события, такие как масштабирование и панорамирование, если вы вернете true из своей функции и будете обрабатывать касание только один раз, если вы вернете false.)

в методе dispatchTouch вы можете проверить отсутствие точек касания, используя event.getPointerCount(). используйте Action_UP для определения того, был ли пользователь уменьшен или нет, вызывая mapview.getZoomLevel(); если вы измените масштаб, вы можете выполнять свои действия.

Ответ 6

i реализовал его следующим образом, и он работает для одиночного/мультитач:

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

Это сработало для меня!

Ответ 7

Попробуйте с помощью этого метода

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

                    @Override
                    public boolean onZoom(ZoomEvent event)
                        {

                            return false;
                        }
                });

Ответ 8

MapView предоставляет встроенные средства масштабирования, которые поддерживают пинч. Если он не работает из коробки, вы можете попробовать установить mapView.setBuiltInZoomControls(true); Таким образом вам не понадобится OnZoomListener.