Как реализовать 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);
8 ответов
Мне пришлось создать подкласс 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, но событие касания будет обнаружено только один раз, если onTouchListener вернет false. Если он вернет true, касание будет обнаруживаться каждый раз, но масштабирование и панорамирование карты не будут работать.
Я собрал весь код сверху и придумал этот класс:
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();
}
Попробуйте через этот метод
map.setMapListener(new MapListener()
{
....
@Override
public boolean onZoom(ZoomEvent event)
{
return false;
}
});
Может быть, немного поздно, но вы пытались с OnOverlayGestureListener?
http://code.google.com/p/mapview-overlay-manager/wiki/OnOverlayGestureListener
Используйте метод dispatchTouch() для обнаружения сенсорных событий на карте и убедитесь, что вы вызываете метод super() для выполнения сенсорных функций карты по умолчанию. (Установка onTouchListener отключит встроенные события, такие как масштабирование и панорамирование, если вы вернете true из своей функции, и будет обрабатывать касание только один раз, если вы вернете false.)
в методе dispatchTouch вы можете проверить отсутствие точек соприкосновения, используя event.getPointerCount(). используйте Action_UP, чтобы определить, уменьшил ли пользователь масштаб или нет, вызвав mapview.getZoomLevel(); если вы обнаружите, что уровень масштабирования изменился, вы можете выполнять свои действия.
Я реализовал это следующим образом, и он работает для одного / мультитач:
@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());
}
}
Это сработало для меня!
Изменить: я считаю, что вы, вероятно, единственный механизм, позволяющий это обнаружение. (Редактирование моего поста для удаления дезинформации) Будет работать расширение MapView и переопределение метода onDraw(). Одним из соображений будет то, как часто запускать код, слушая масштабирование. Например, при масштабировании onDraw можно вызывать десятки раз, каждый с разным уровнем масштабирования. Это может привести к снижению производительности, если ваш слушатель стреляет каждый раз. Вы можете регулировать это, определив, что изменение масштаба произошло, и затем подождать, пока уровень масштабирования будет одинаковым на двух последующих перерисовках, прежде чем запускать событие. Все зависит от того, как вы хотите, чтобы ваш код вызывался.
MapView предоставляет встроенные элементы управления масштабированием, которые поддерживают пинч. Если это не работает из коробки, вы можете попробовать установить mapView.setBuiltInZoomControls(true);
Таким образом, вам не нужен OnZoomListener.