Android MapView не может удалить маркер

Я использую locationManager и ItemizedOverlay для рисования маркера My Location, проблема в том, что когда срабатывает onLocationChanged, я получаю новый маркер, а не последний перемещается в новое место, вот мой код onLocationChanged:

public void onLocationChanged(Location location) {
  myOverlay object1 = new myOverlay(getResources().getDrawable(R.drawable.arrow),MyMap);

  if(location!=null){
   MyMap.invalidate();
   GeoPoint MyPos = new GeoPoint(microdegrees(location.getLatitude()),microdegrees(location.getLongitude()));
   MyController.animateTo(MyPos);
   object1.addPoint(MyPos,"Ma position","Ma position");
   MyMap.getOverlays().add(object1);
  }

 }

Не могли бы вы помочь мне решить эту проблему?

Большое спасибо.

КартаАктивность:

public class Main extends MapActivity implements LocationListener {
  /** Called when the activity is first created. */
  MapView MyMap;
  MapController MyController;

    @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);

      MyMap=(MapView)findViewById(R.id.MyGMap);
      MyMap.setBuiltInZoomControls(true);

      try {
      getEventsFromAnXML(this);

     } catch (XmlPullParserException e) {
      e.printStackTrace();
     } catch (IOException e) {
      e.printStackTrace();
     }
     int j=0;

     myOverlay object = new myOverlay(getResources().getDrawable(R.drawable.marker),MyMap);
     while( j<agencies.size()){
         GeoPoint point = new GeoPoint(microdegrees(agencies.get(j).getLatitude()),microdegrees(agencies.get(j).getLongitude()));
         String Tit;
         String Des;
         Tit=agencies.get(j).getTspTitle();
         Des=agencies.get(j).getTspTitle() + "\nAgence: " + agencies.get(j).getTitle() +
             "\nTél: " + agencies.get(j).getPhone();
         object.addPoint(point,Tit,Des);
         j=j+1;
     }


     MyMap.getOverlays().add(object);
     MyController=MyMap.getController();
     MyController.setZoom(12);

     LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
     lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f, this);

  }

  private int microdegrees(double value){
      return (int)(value*1000000);
  }


  boolean na=false;
  List<Agency> agencies = new ArrayList<Agency>();
  Agency agency=new Agency();
  int i=0;
  String TempTspTitle;
  String TempTspPhone;
  Boolean TempTspEnabled;
  private String getEventsFromAnXML(Activity activity)
  throws XmlPullParserException, IOException
  {
   StringBuffer stringBuffer = new StringBuffer();
   Resources res = activity.getResources();
   XmlResourceParser xpp = res.getXml(R.xml.hotels);
   xpp.next();
   int eventType = xpp.getEventType();

   while (eventType != XmlPullParser.END_DOCUMENT)
   {
    if(eventType == XmlPullParser.START_DOCUMENT)
    {
     stringBuffer.append("--- Start XML ---");
    }
    else if(eventType == XmlPullParser.START_TAG)
    {
        if (xpp.getName().equals("DataBase")){
            String name=xpp.getAttributeValue(null, "name");
            agency.setTspTitle(name);
            TempTspTitle=name;
            na=true;
        }

        if (xpp.getName().equals("DataBaseEnabled")){
            xpp.next();
            agency.setTspEnabled(Boolean.parseBoolean(xpp.getText()));
            TempTspEnabled=Boolean.parseBoolean(xpp.getText());
            xpp.nextTag();
        }
        if (xpp.getName().equals("Title")){
            xpp.next();
            agency.setTitle(xpp.getText());
            na=false;
            xpp.nextTag();
        }
        if (xpp.getName().equals("Address")){
            xpp.next();
            agency.setAddress(xpp.getText());
            xpp.nextTag();
        }

        if (xpp.getName().equals("Phone") && na==true){
            xpp.next();
            agency.setTspPhone(xpp.getText());
            TempTspPhone=xpp.getText();
            xpp.nextTag();
        }else{
            if (xpp.getName().equals("Phone") && na==false){
                xpp.next();
                agency.setPhone(xpp.getText());
                xpp.nextTag();
            }

        }

        if (xpp.getName().equals("Fax")){
            xpp.next();
            agency.setFax(xpp.getText());
            xpp.nextTag();
        }

        if (xpp.getName().equals("e-Mail")){
            xpp.next();
            agency.setMail(xpp.getText());
            xpp.nextTag();
        }
        if (xpp.getName().equals("Latitude")){
            xpp.next();
            agency.setLatitude(Double.parseDouble(xpp.getText()));
            xpp.nextTag();
        }
        if (xpp.getName().equals("Longitude")){
            xpp.next();
            agency.setLongitude(Double.parseDouble(xpp.getText()));
        }


    }
    else if(eventType == XmlPullParser.END_TAG)
    {
        if (xpp.getName().equals("DataBase") ){
            agency = new Agency();
        }else if (xpp.getName().equals("Agency")){
            agencies.add(i,agency);
            i=i+1;
            agency = new Agency();
            agency.setTspTitle(TempTspTitle);
            agency.setTspPhone(TempTspPhone);
            agency.setTspEnabled(TempTspEnabled);
        }

    }


    eventType = xpp.next();
   }
   stringBuffer.append("\n" + "Size: " + agencies.size());
   return stringBuffer.toString();
  }

  @Override
    protected boolean isRouteDisplayed() {
        return false;
    }


    public void onLocationChanged(Location location) {
        myOverlay object1 = new myOverlay(getResources().getDrawable(R.drawable.arrow),MyMap);

        if(location!=null){
            MyMap.getOverlays().remove(object1);
            MyMap.invalidate();
            GeoPoint MyPos = new GeoPoint(microdegrees(location.getLatitude()),microdegrees(location.getLongitude()));
            MyController.animateTo(MyPos);
            object1.addPoint(MyPos,"Ma position","Ma position");
            MyMap.getOverlays().add(object1);
        }

    }

    public void onProviderDisabled(String provider) {
        // TODO Auto-generated method stub

    }

    public void onProviderEnabled(String provider) {
        // TODO Auto-generated method stub

    }

    public void onStatusChanged(String provider, int status, Bundle extras) {
        // TODO Auto-generated method stub

    }

и класс myOverlay:

public class myOverlay extends ItemizedOverlay<OverlayItem>{

    List<OverlayItem> points= new ArrayList<OverlayItem>();
    private Drawable marker=null;  
    private Context c;
    public myOverlay(Drawable marker, MapView mapView) {
        super(marker);
        this.marker=marker;
        c=mapView.getContext();
    }

    @Override
    protected OverlayItem createItem(int i) {
        return (points.get(i));
    }

    public void draw(Canvas canvas,MapView mapView, boolean shadow){
        super.draw(canvas, mapView, shadow);
        boundCenterBottom(marker);
    }

    @Override
    public int size() {
        return points.size();
    }

    public void addPoint(GeoPoint point, String Titre, String Desc){
        this.points.add(new OverlayItem(point,Titre,Desc));
        populate();
    }

    public void removePoint(){
        this.points.clear();
        populate();
    }

    @Override
    protected boolean onTap(int i){
        Toast.makeText(c, points.get(i).getSnippet(), Toast.LENGTH_SHORT).show();
        return (true);
    }

  }      

    }

person Houssem    schedule 08.01.2011    source источник


Ответы (3)


по предложению Дейва это устранило проблему:

  public void onLocationChanged(Location location) {
    if(mMyOverlay == null) {
        mMyOverlay = new myOverlay(getResources().getDrawable(R.drawable.arrow),MyMap);
        MyMap.getOverlays().add(mMyOverlay);
    }else{
        MyMap.getOverlays().remove(mMyOverlay);
        MyMap.invalidate();
        mMyOverlay = new myOverlay(getResources().getDrawable(R.drawable.arrow),MyMap);
        MyMap.getOverlays().add(mMyOverlay);
    }
    if(location!=null){
        MyMap.invalidate();
        GeoPoint MyPos = new GeoPoint(microdegrees(location.getLatitude()),microdegrees(location.getLongitude()));
        MyController.animateTo(MyPos);
        mMyOverlay.addPoint(MyPos,"Ma position","Ma position");
     }

Спасибо..

person Houssem    schedule 08.01.2011

getOverlays() возвращает список объектов Overlay в вашем MapView. Каждый раз, когда местоположение обновляется, ваш код добавляет еще одно наложение в этот список. Вам нужно удалить предыдущее наложение или каждый раз полностью очищать список.

Итак, в вашем методе вызовите getOverlays().clear() перед добавлением нового наложения.

Изменить, в качестве альтернативы, может быть, это укажет вам правильное направление? Я точно не знаю, как работает ваш класс myOverlay, поэтому, надеюсь, вы сможете заполнить пробелы!

protected myOverlay mMyOverlay; 

public void onLocationChanged(Location location) {
  if(mMyOverlay == null) {
      mMyOverlay = new myOverlay(getResources().getDrawable(R.drawable.arrow),MyMap);
      MyMap.getOverlays().add(mMyOverlay);

  if(location!=null){
      MyMap.invalidate();
      GeoPoint MyPos = new GeoPoint(microdegrees(location.getLatitude()),microdegrees(location.getLongitude()));
      MyController.animateTo(MyPos);
      mMyOverlays.setPoint(MyPos,"Ma position","Ma position");
   }
}
person Dave    schedule 08.01.2011
comment
попробовал getOverlays().clear(), он работает, но удаляет все существующие наложения (у меня есть маркеры в другом наложении, которые я должен отображать), а также пробовал getOverlays().remove(object1), и у меня есть новый маркер в дополнение к последнему. - person Houssem; 08.01.2011
comment
Вам нужно следить за наложениями, которые вы хотите оставить себе. MapView API не может управлять ими за вас. Возможно, сделайте оверлей локальным для вашего класса (например, mMyOverlay), создайте его экземпляр в своем конструкторе и добавьте в список оверлеев. Затем просто обновите этот объект напрямую, когда это необходимо, а не удаляйте/добавляйте в список после каждого обновления. - person Dave; 08.01.2011

Используйте ItemizedOverlay и, как предложил Дейв, отслеживайте тот, который вы хотите переместить, а затем либо удалите отслеживаемый OverlayItem и добавьте новый, либо возьмите отслеженный, получите его маркер или MapPoint и сбросьте его координаты широты/долготы на новые координаты местоположения. Вам также может понадобиться вызвать mapView.invalidate(), чтобы принудительно перерисовать.

person John J Smith    schedule 08.01.2011
comment
Вы также должны вызвать populate() для ItemizedOverlay после того, как вы изменили/удалили маркер в любом резервном хранилище, которое использует оверлей (ArrayList, база данных Cursor и т. д.). - person CommonsWare; 08.01.2011
comment
извините, я сбит с толку, взгляните на мой класс MapActivity и myOverlay (обновление) - person Houssem; 08.01.2011