如何检测Android MapView是否已平移或缩放?
我正在创建一个Android应用程序,它根据MapView的可见区域搜索项目。有没有办法在我的MapView上设置一个侦听器来检测地图何时被平移或缩放?我能想到的唯一方法是扩展MapView并覆盖OnTouchEvent并观察up操作。这将告诉您用户已完成移动,您可以获取lat/lon span以确定您应该签出的区域。尝试mapview overlayer manager,它是android地图overlayer的扩展 它有一些简化的OnTestureListener,很少有示例:如何检测Android MapView是否已平移或缩放?,android,android-mapview,Android,Android Mapview,我正在创建一个Android应用程序,它根据MapView的可见区域搜索项目。有没有办法在我的MapView上设置一个侦听器来检测地图何时被平移或缩放?我能想到的唯一方法是扩展MapView并覆盖OnTouchEvent并观察up操作。这将告诉您用户已完成移动,您可以获取lat/lon span以确定您应该签出的区域。尝试mapview overlayer manager,它是android地图overlayer的扩展 它有一些简化的OnTestureListener,很少有示例: onSing
onSingleTap(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem)
onDoubleTap(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem)
onLongPress(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem)
onZoom(ZoomEvent, ManagedOverlay)
onScrolled(...)
链接:希望能有所帮助遗憾的是,MapView工具中没有内置的功能来实现这一点(这是一个奇怪的疏忽,因为JavaScript SDK和iOS SDK中都有此功能) 不过,通过使用Runnable并轮询MapView,您可以很容易地处理这个问题。我通过跟踪以下各项的“最后”状态来实现此目的:
getLatitudeSpan();
getLongitudeSpan();
getCenter();
getZoomLevel();
然后将其与当前值进行比较。如果的值已更改,则表示地图视图已移动。如果没有,你什么也做不了
无论哪种方式,重新安排runnable在500毫秒左右后再次运行,并重复该过程。您可以使用onResume()和onPause()删除Runnable的回调,并根据需要重新启动它。MapView类可以使用onLayout方法跟踪更改 i、 e
可以创建扩展MapView的SimpleMapView
public class SimpleMapView extends MapView {
private int currentZoomLevel = -1;
private GeoPoint currentCenter;
private List<ZoomChangeListener> zoomEvents = new ArrayList<ZoomChangeListener>();
private List<PanChangeListener> panEvents = new ArrayList<PanChangeListener>();
public SimpleMapView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public SimpleMapView(Context context, String apiKey) {
super(context, apiKey);
}
public SimpleMapView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
*
* @return
*/
public int[][] getBounds() {
GeoPoint center = getMapCenter();
int latitudeSpan = getLatitudeSpan();
int longtitudeSpan = getLongitudeSpan();
int[][] bounds = new int[2][2];
bounds[0][0] = center.getLatitudeE6() - (latitudeSpan / 2);
bounds[0][1] = center.getLongitudeE6() - (longtitudeSpan / 2);
bounds[1][0] = center.getLatitudeE6() + (latitudeSpan / 2);
bounds[1][1] = center.getLongitudeE6() + (longtitudeSpan / 2);
return bounds;
}
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
GeoPoint centerGeoPoint = this.getMapCenter();
if (currentCenter == null ||
(currentCenter.getLatitudeE6() != centerGeoPoint.getLatitudeE6()) ||
(currentCenter.getLongitudeE6() != centerGeoPoint.getLongitudeE6()) ) {
firePanEvent(currentCenter, this.getMapCenter());
}
currentCenter = this.getMapCenter();
}
return super.onTouchEvent(ev);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if(getZoomLevel() != currentZoomLevel){
fireZoomLevel(currentZoomLevel, getZoomLevel());
currentZoomLevel = getZoomLevel();
}
}
@Override
public void setSatellite(boolean on){
super.setSatellite(on);
}
@Override
public MapController getController(){
return super.getController();
}
private void fireZoomLevel(int old, int current){
for(ZoomChangeListener event : zoomEvents){
event.onZoom(old, current);
}
}
private void firePanEvent(GeoPoint old, GeoPoint current){
for(PanChangeListener event : panEvents){
event.onPan(old, current);
}
}
public void addZoomChangeListener(ZoomChangeListener listener){
this.zoomEvents.add(listener);
}
public void addPanChangeListener(PanChangeListener listener){
this.panEvents.add(listener);
}
}
以前的问题,但我写了一个名为ExMapView的类,它在地图区域开始更改(onRegionBeginChange)和停止更改(onRegionEndChange)时触发事件。此类用于旧的MapView,而不是V2.0。希望它能帮助别人
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 ExMapView extends MapView {
private static final String TAG = ExMapView.class.getSimpleName();
private static final int DURATION_DEFAULT = 700;
private OnRegionChangedListener onRegionChangedListener;
private GeoPoint previousMapCenter;
private int previousZoomLevel;
private int changeDuration; // This is the duration between when the user stops moving the map around and when the onRegionEndChange event fires.
private boolean isTouched = false;
private boolean regionChanging = false;
private Runnable onRegionEndChangeTask = new Runnable() {
public void run() {
regionChanging = false;
previousMapCenter = getMapCenter();
previousZoomLevel = getZoomLevel();
if (onRegionChangedListener != null) {
onRegionChangedListener.onRegionEndChange(ExMapView.this, previousMapCenter, previousZoomLevel);
}
}
};
public ExMapView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ExMapView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public ExMapView(Context context, String apiKey) {
super(context, apiKey);
init();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
isTouched = event.getAction() != MotionEvent.ACTION_UP;
return super.onTouchEvent(event);
}
@Override
public void computeScroll() {
super.computeScroll();
// If the map region is still changing (user is still scrolling or zooming), reset timer for onRegionEndChange.
if ((!isTouched && !getMapCenter().equals(previousMapCenter)) || (previousZoomLevel != getZoomLevel())) {
// If the region has just begun changing, fire off onRegionBeginChange event.
if (!regionChanging) {
regionChanging = true;
if (onRegionChangedListener != null) {
onRegionChangedListener.onRegionBeginChange(this, previousMapCenter, previousZoomLevel);
}
}
// Reset timer for onRegionEndChange.
removeCallbacks(onRegionEndChangeTask);
postDelayed(onRegionEndChangeTask, changeDuration);
}
}
private void init() {
changeDuration = DURATION_DEFAULT;
previousMapCenter = getMapCenter();
previousZoomLevel = getZoomLevel();
}
public void setOnRegionChangedListener(OnRegionChangedListener listener) {
onRegionChangedListener = listener;
}
public void setChangeDuration(int duration) {
changeDuration = duration;
}
public interface OnRegionChangedListener {
public abstract void onRegionBeginChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel);
public abstract void onRegionEndChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel);
}
}
你有这样的例子吗?“遗憾的是,MapView工具中没有内置的功能”不,onLayout方法非常优雅地处理了这一点,请参见我的答案。在姜饼上测试三种地图交互(用手指平移、通过控件缩放、用两个手指捏/反向捏),这就是我得到的:1)平移:有多个更改为true的onLayout事件2)缩放:有一个更改为true的事件,多个更改为false的事件3)收缩/反向收缩:没有更改为true的事件,多个更改为false的事件。因此,使用此方法,您可以通过控件更改来检测手指的简单平移/缩放,但无法检测通过按压/反向按压所做的更改。如果用户在向上操作后将贴图固定下来,则此方法不起作用
<com.androidnatic.maps.SimpleMapView android:clickable="true"
android:layout_height="match_parent" android:id="@+id/mapView"
android:layout_width="match_parent"
android:apiKey="xxx">
</com.androidnatic.maps.SimpleMapView>
mapView.addPanChangeListener(new PanChangeListener() {
@Override
public void onPan(GeoPoint old, GeoPoint current) {
//TODO
}
});
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 ExMapView extends MapView {
private static final String TAG = ExMapView.class.getSimpleName();
private static final int DURATION_DEFAULT = 700;
private OnRegionChangedListener onRegionChangedListener;
private GeoPoint previousMapCenter;
private int previousZoomLevel;
private int changeDuration; // This is the duration between when the user stops moving the map around and when the onRegionEndChange event fires.
private boolean isTouched = false;
private boolean regionChanging = false;
private Runnable onRegionEndChangeTask = new Runnable() {
public void run() {
regionChanging = false;
previousMapCenter = getMapCenter();
previousZoomLevel = getZoomLevel();
if (onRegionChangedListener != null) {
onRegionChangedListener.onRegionEndChange(ExMapView.this, previousMapCenter, previousZoomLevel);
}
}
};
public ExMapView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ExMapView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public ExMapView(Context context, String apiKey) {
super(context, apiKey);
init();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
isTouched = event.getAction() != MotionEvent.ACTION_UP;
return super.onTouchEvent(event);
}
@Override
public void computeScroll() {
super.computeScroll();
// If the map region is still changing (user is still scrolling or zooming), reset timer for onRegionEndChange.
if ((!isTouched && !getMapCenter().equals(previousMapCenter)) || (previousZoomLevel != getZoomLevel())) {
// If the region has just begun changing, fire off onRegionBeginChange event.
if (!regionChanging) {
regionChanging = true;
if (onRegionChangedListener != null) {
onRegionChangedListener.onRegionBeginChange(this, previousMapCenter, previousZoomLevel);
}
}
// Reset timer for onRegionEndChange.
removeCallbacks(onRegionEndChangeTask);
postDelayed(onRegionEndChangeTask, changeDuration);
}
}
private void init() {
changeDuration = DURATION_DEFAULT;
previousMapCenter = getMapCenter();
previousZoomLevel = getZoomLevel();
}
public void setOnRegionChangedListener(OnRegionChangedListener listener) {
onRegionChangedListener = listener;
}
public void setChangeDuration(int duration) {
changeDuration = duration;
}
public interface OnRegionChangedListener {
public abstract void onRegionBeginChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel);
public abstract void onRegionEndChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel);
}
}