Часы исследования и какое-то решение было найдено.У него есть некоторые плюсы и минусы, которые я опишу далее.
Главное, что мы должны сделать, это переопределить некоторые методы MapView для обработки его поведения при рисовании.В случае, если мы не можем переопределить метод draw (), мы должны найти другой путь. Есть еще одна производная от View, которая может быть переопределена - метод computeScroll ().Он вызывается повторно, так как карта продолжает заполняться.Все, что нам нужно сделать, это установить некоторый порог времени, чтобы поймать, если computeScroll больше не вызывается на этот раз.
Вот что я сделал:
import java.util.Timer;
import java.util.TimerTask;
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 EnhancedMapView extends MapView {
public interface OnZoomChangeListener {
public void onZoomChange(MapView view, int newZoom, int oldZoom);
}
public interface OnPanChangeListener {
public void onPanChange(MapView view, GeoPoint newCenter, GeoPoint oldCenter);
}
private EnhancedMapView _this;
// Set this variable to your preferred timeout
private long events_timeout = 500L;
private boolean is_touched = false;
private GeoPoint last_center_pos;
private int last_zoom;
private Timer zoom_event_delay_timer = new Timer();
private Timer pan_event_delay_timer = new Timer();
private EnhancedMapView.OnZoomChangeListener zoom_change_listener;
private EnhancedMapView.OnPanChangeListener pan_change_listener;
public EnhancedMapView(Context context, String apiKey) {
super(context, apiKey);
_this = this;
last_center_pos = this.getMapCenter();
last_zoom = this.getZoomLevel();
}
public EnhancedMapView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EnhancedMapView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setOnZoomChangeListener(EnhancedMapView.OnZoomChangeListener l) {
zoom_change_listener = l;
}
public void setOnPanChangeListener(EnhancedMapView.OnPanChangeListener l) {
pan_change_listener = l;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == 1) {
is_touched = false;
} else {
is_touched = true;
}
return super.onTouchEvent(ev);
}
@Override
public void computeScroll() {
super.computeScroll();
if (getZoomLevel() != last_zoom) {
// if computeScroll called before timer counts down we should drop it and start it over again
zoom_event_delay_timer.cancel();
zoom_event_delay_timer = new Timer();
zoom_event_delay_timer.schedule(new TimerTask() {
@Override
public void run() {
zoom_change_listener.onZoomChange(_this, getZoomLevel(), last_zoom);
last_zoom = getZoomLevel();
}
}, events_timeout);
}
// Send event only when map's center has changed and user stopped touching the screen
if (!last_center_pos.equals(getMapCenter()) || !is_touched) {
pan_event_delay_timer.cancel();
pan_event_delay_timer = new Timer();
pan_event_delay_timer.schedule(new TimerTask() {
@Override
public void run() {
pan_change_listener.onPanChange(_this, getMapCenter(), last_center_pos);
last_center_pos = getMapCenter();
}
}, events_timeout);
}
}
}
Затем вы должны зарегистрировать обработчики событий в вашей MapActivity, какthis:
public class YourMapActivity extends MapActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mv = new EnhancedMapView(this, "<your Maps API key here>");
mv.setClickable(true);
mv.setBuiltInZoomControls(true);
mv.setOnZoomChangeListener(new EnhancedMapView.OnZoomChangeListener() {
@Override
public void onZoomChange(MapView view, int newZoom, int oldZoom) {
Log.d("test", "zoom changed from " + oldZoom + " to " + newZoom);
}
}
mv.setOnPanChangeListener(new EnhancedMapView.OnPanChangeListener() {
public void onPanChange(MapView view, GeoPoint newCenter, GeoPoint oldCenter) {
Log.d("test", "center changed from " + oldCenter.getLatitudeE6() + "," + oldCenter.getLongitudeE6() + " to " + newCenter.getLatitudeE6() + "," + newCenter.getLongitudeE6());
}
}
}
А как насчет преимуществ и недостатков этого подхода?
Преимущества:
- События обрабатывают карту в любом случае, когда карта была панорамирована или масштабирована.Событие касания, используемые аппаратные клавиши, даже события, запускаемые программным способом, обрабатываются (например, методы setZoom () или animate ()).
- Возможность пропустить ненужную загрузку данных, если пользователь несколько раз быстро нажимает кнопку увеличения.Событие сработает только после того, как щелчки прекратятся.
Недостатки:
- Отменить масштабирование или панорамирование совсем невозможно (возможно, я добавлю эту способность в будущем)
Надеюсь, что это немногокласс поможет вам.