使用MapView开发地图应用时,经常遇到的问题是如何感知用户平移了地图或者缩放了地图。
在百度上找不到答案,无意中,发现一个国外网站有一个解决案,和大家分享一下。
参考文章
http://d.hatena.ne.jp/sei10sa10/20110801/1312191680
http://stackoverflow.com/questions/3567420/how-to-catch-that-map-panning-and-zoom-are-really-finished
其核心就是重写MapView,复写computeScroll和onTouchEvent
首先是xml中的定义
<com.android.practice.map.MyMapView android:id="@+id/map_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" <-- 初学者常犯错误,不加这个选项,你无法拖动地图 android:apiKey="Google Maps API key" />
别忘记还有下面的配置
<uses-library android:name="com.google.android.maps" android:required="true" />
不然启动程序就会异常退出
还有必要的权限
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
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); } } }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); map = new EnhancedMapView(this, "0gQ_MbqIw4SHBvnFETsLCjx1kU2TXYXnGW5eIYA"); map.setClickable(true); map.setBuiltInZoomControls(true); map.setBuiltInZoomControls(true); MapController mapController = map.getController(); mapController.setZoom(14); map.setOnZoomChangeListener(new EnhancedMapView.OnZoomChangeListener() { @Override public void onZoomChange(MapView view, int newZoom, int oldZoom) { Log.d("test", "zoom changed from " + oldZoom + " to " + newZoom); } }); map.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()); } }); setContentView(map); }