Проблемы с наложением карты Android

Есть ли способ реализовать прослушиватель масштабирования, который может запускать события, как только изменяется уровень масштабирования. До сих пор мне удавалось с помощью метода onUserinteraction вручную проверять изменение уровня масштабирования. Другое дело, что я хочу динамически добавлять/удалять оверлеи. то, что я сделал до сих пор, находится в методе onUserinteraction, я вызываю функцию, которая динамически добавляет оверлеи, используя функцию mapOverlays.add(), и добавление действительно происходит динамически. Но почему-то функция mapOverlays.remove() не удаляет наложения

     //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)
   {

   }
}

person Black Mamba    schedule 22.09.2011    source источник


Ответы (3)


Чтобы реализовать собственный обработчик масштабирования и добавить прослушиватель, вам необходимо создать свой подкласс MapView. Во-первых, давайте создадим интерфейс для OnZoomListener. Обратите внимание, что вы можете изменить интерфейс в соответствии с вашими потребностями, ниже приведен только скелетный код, с которого вы можете начать.


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);
}

Теперь вам нужен подкласс, который будет вызывать этот OnZoomListener всякий раз, когда изменяется масштаб. Вот скелет кода для того, что является расширением этого SO-ответа


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();
        }
    }
}

Теперь вы можете использовать MyMapView в макете вместо стандартного MapView. Примечание. Пакет кода com.so4729255 используется только для тестирования.


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

И, наконец, добавьте OnZoomListener в свой код. В приведенном ниже коде просто показан Toast для иллюстрации использования, вы можете делать там все, что вам нужно.


 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();
            }
        });

Что касается вашего второго вопроса, как все ответили, вызов MapView.invalidate() должен перерисовать карту с ее новым состоянием, поскольку это заставит представление перерисовываться на документацию API

person momo    schedule 22.09.2011
comment
это хорошо, обязательно постараюсь вернуться, мне нужно знать как можно скорее, почему я не могу удалить с помощью mapOverlays.remove(itemizedOverlayname); любая немедленная помощь будет принята с благодарностью..... Большое спасибо - person Black Mamba; 22.09.2011
comment
Вы пытались вызвать MapView.invalidate() вместо mapView.postInvalidate()? invalidate() должен немедленно перерисовывать карту (по крайней мере, для всех карт, которые я делал раньше) в соответствии с документацией. - person momo; 22.09.2011
comment
сделал, и он не работает, я только что заметил, что метод удаления удаляет только первое вхождение объекта наложения, но мой ошибочный код добавляет одно и то же наложение несколько раз, поэтому я не могу увидеть результат. исправлю и правильно отвечу на мой собственный вопрос .... кстати, я реализую вашу идею слушателя масштабирования !!! - person Black Mamba; 22.09.2011

ну, вам нужно обновить карту, используя

mapview.invalidate()

postInvalidate отправляет запрос на аннулирование в потоке пользовательского интерфейса, а вызов invalidate() немедленно аннулирует представление.

person Reno    schedule 22.09.2011

Когда уровень масштабирования изменяется, карта перерисовывается, поэтому я просто добавляю этот тип функциональности в метод рисования наложения, например так:

e@Override
public void draw(Canvas canvas, MapView mapv, boolean shadow)
{       
    int zoom = mapv.getZoomLevel();

    switch(zoom)
    {
        case 19:
            setMarkersForZoomLevel19();
            break;
        case 18:
            setMarkersForZoomLevel18();
            break;
        case 17:
            setMarkersForZoomLevel17();
            break;
        case 16:
            setMarkersForZoomLevel16();
            break;
        default:
            // Hide the markers or remove the overlay from the map view.                
            mapv.getOverlays().clear();
    }       

    // Putting this call here rather than at the beginning, ensures that
    // the Overlay items are drawn over the top of canvas stuff e.g. route lines.
    super.draw(canvas, mapv, false);        
}

и когда вы удаляете наложение, не забудьте вызвать mapView.invalidate().

person John J Smith    schedule 22.09.2011