Search code examples
androiddictionaryoverlays

Android Map Overlay Issues


Is there any way i can implement a zoom listener that can trigger events as soon as the zoom level changes. So far, i have managed with the onUserinteraction method manually checking for changing zoom-level. Another thing is i to want add/remove overlays dynamically. what i,ve done so far is in the onUserinteraction method, i call a function which adds the overlays dynamically, using mapOverlays.add() function and the addition actually does happen dynamically. But somehow mapOverlays.remove() function is not removing the overlays

     //Function for adding first set of markers
     public void setOverlay()
{
    worldLength = World.length;
    mapOverlays = mapView.getOverlays();
    drawable0 = this.getResources().getDrawable(R.drawable.marker);
    itemizedOverlay0 = new MyItemizedOverlay(drawable0);
    for (int i = 0; i < worldLength; i++)
    {
        itemizedOverlay0.addOverlay(World[i]);
    }
    mapOverlays.add(itemizedOverlay0);
    mapView.postInvalidate();
}
     //Function for adding second set of markers
     public void setOverlay1() 
     {
      mapView.setStreetView(true);
      usaLength = USA.length;
      mexicoLength = Mexico.length;
               mapOverlays = mapView.getOverlays();
        drawable1 = this.getResources().getDrawable(R.drawable.marker);
        itemizedOverlay1 = new MyItemizedOverlay(drawable1);
        itemizedOverlay2 = new MyItemizedOverlay(drawable1);


        for (int i = 0; i < usaLength; i++) {
            itemizedOverlay1.addOverlay(USA[i]);
        }
        for (int i = 0; i < mexicoLength; i++) {
            itemizedOverlay2.addOverlay(Mexico[i]);
        }

        mapOverlays.add(itemizedOverlay1);
        mapOverlays.add(itemizedOverlay2);


    mapView.postInvalidate();

}

     public void onUserInteraction() {
   super.onUserInteraction();
   if(mapView.getZoomLevel()>3)
   {
       mapOverlays.remove(itemizedOverlay0);
       setOverlay1();
                 //the above happens
   }
   else if(mapView.getZoomLevel()<=3 && mapOverlays.size()>5)
   {
       mapOverlays.remove(itemizedOverlay1);
       mapOverlays.remove(itemizedOverlay2);
                 //the above doesn't
       setOverlay();   
   }
   else if(mapView.getZoomLevel()<=3)
   {

   }
}

Solution

  • In order to implement your custom zoom handler and add a listener, you need to be create your subclass of the MapView. First, let's create the interface for the OnZoomListener. Note that you could change the interface to suit your need, the following is just a skeleton code for you to start with

    
    public interface OnZoomListener {
        /***
         * /**
         * Called when there is a zoom changes 
         * @param mapView Reference to the current map view
         * @param currentZoom The current zoom, set to -1 initially
         * @param newZoom The new zoom level
         */
         public void onZoomChanged(MapView mapView, int currentZoom, int newZoom);
    }
    

    Now, you need a subclass that will call this OnZoomListener whenever the zoom changes. Here is the skeleton code for that which is an extension of this SO Answer

    
    public class MyMapView extends MapView {
        int oldZoomLevel=-1;
        OnZoomListener onZoomListener;
    
        public MyMapView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        public MyMapView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MyMapView(Context context, String apiKey) {
            super(context, apiKey);
        }
    
        public void setOnZoomListener(OnZoomListener onZoomListener) {
            this.onZoomListener = onZoomListener;
        }
    
        @Override
        public void dispatchDraw(Canvas canvas) {
            super.dispatchDraw(canvas);
            int newZoom = this.getZoomLevel();
    
            if (newZoom != oldZoomLevel) {
                // dispatch the listeners
                if(oldZoomLevel != -1 &&  onZoomListener != null) {
                    onZoomListener.onZoomChanged(this, oldZoomLevel, newZoom);
                }
    
                // update the new zoom level
                oldZoomLevel = getZoomLevel();
            }
        }
    }
    

    Now you could use MyMapView in your layout instead of the standard MapView. Note: The code package com.so4729255 is what I use for testing only.

    
      <com.so4729255.MyMapView
                    android:id="@+id/mapview"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:enabled="true"
                    android:apiKey="YOUR API KEY"
                    android:clickable="true"
            />
    

    And finally add the OnZoomListener in your code. The code below just show the Toast for illustration of usage, you could do whatever you need to do there

    
     MyMapView mapView = (MyMapView)this.findViewById(R.id.mapview);
            mapView.setOnZoomListener(new OnZoomListener() {
                public void onZoomChanged(MapView mapView, int currentZoom,
                        int newZoom) {
                    // implement your handler here
                    Toast t = Toast.makeText(WebViewMain.this, "Zoom has changed from " + currentZoom + " to " + 
                            newZoom, 500);
                    t.show();
                }
            });
    

    As for your second question, as everyone has answered, calling MapView.invalidate() should repaint the map with its new state as it will force the View to redraw per the API documentation