【问题标题】:How can I detect if an Android MapView has been panned or zoomed?如何检测 Android MapView 是否已平移或缩放?
【发布时间】:2010-02-24 18:54:20
【问题描述】:

我正在创建一个基于 MapView 的可见区域搜索项目的 Android 应用。有没有办法在我的 MapView 上设置一个监听器来检测地图何时被平移或缩放?

【问题讨论】:

  • 你有这方面的例子吗?

标签: android android-mapview


【解决方案1】:

试试mapview-overlay-manager,它是android地图覆盖层的扩展,

它有一些简化的 OnGestureListener,几个例子:

onSingleTap(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem)

onDoubleTap(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem)

onLongPress(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem)

onZoom(ZoomEvent, ManagedOverlay)

onScrolled(...)

link:http://code.google.com/p/mapview-overlay-manager/希望对你有帮助

【讨论】:

    【解决方案2】:

    您可以创建一个扩展 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);
        }
    }
    

    您拥有可以放置平移或缩放代码的侦听器。 然后在你的xml中:

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

    然后你可以在你的代码中指定 Pan Listener:

    mapView.addPanChangeListener(new PanChangeListener() {
    
                @Override
                public void onPan(GeoPoint old, GeoPoint current) {
                              //TODO
                            }
            });
    

    【讨论】:

      【解决方案3】:

      遗憾的是,在 MapView 工具中没有内置功能来执行此操作(这是一个奇怪的疏忽,因为此功能在 JavaScript SDK 和 iOS SDK 中)。

      您可以通过使用 Runnable 并仅轮询 MapView 来轻松处理此问题。我通过跟踪以下的“最后”状态来做到这一点:

      getLatitudeSpan();
      getLongitudeSpan();
      getCenter();
      getZoomLevel();
      

      然后将它们与当前值进行比较。如果 的值发生变化,您就知道地图视图已移动。如果没有,你什么也做不了。

      无论哪种方式,在 500 毫秒左右后重新安排可运行对象以进行另一次运行,然后重复该过程。您可以使用 onResume() 和 onPause() 来移除 Runnable 的回调并根据需要重新启动它。

      【讨论】:

      • “遗憾的是,在 MapView 工具中没有内置功能可以做到这一点”不,onLayout 方法可以很好地处理这个问题,请参阅我的答案作为示例。
      【解决方案4】:

      MapView 类可以使用 onLayout 方法跟踪更改。

      class CustomMapView extends MapView {
      
          protected void onLayout(boolean changed,int left, int right, int top, int bottom){
              super.onLayout(changed,left, right, top, bottom);
              if(changed){
              // do something special
              }
          }
      }
      

      【讨论】:

      • 在 Gingerbread 上测试三个地图交互(用手指平移,通过控件缩放,用两根手指捏/反向捏),这就是我得到的:1)平移:有多个 onLayout 事件已更改=true 2) ZOOM:有一个事件changed=true,多个事件changed=false 3) PINCH / REVERSE PINCH:没有事件changed=true,多个事件changed=false。因此,使用这种方法,您可以通过控件更改检测简单的 PAN 手指 / ZOOM,但您无法检测到使用 PINCH / REVERSE PINCH 所做的更改。
      【解决方案5】:

      我能想到的唯一方法是扩展 MapView 并覆盖 OnTouchEvent 并注意 Up 动作。这将告诉您用户已完成移动,您可以获取纬度/经度跨度以确定您应该检查的区域。

      【讨论】:

      • 如果用户扔掉地图,这将不起作用,因为地图将在 UP 操作后稳定
      【解决方案6】:

      老问题,但我不久前写了一个名为 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);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-07
        • 1970-01-01
        • 2011-12-02
        • 2011-10-18
        • 1970-01-01
        • 2013-11-08
        • 1970-01-01
        • 2021-04-18
        相关资源
        最近更新 更多