2011-05-16 37 views
12

Estoy haciendo un rastreador de GPS usando Google Maps API y mostrando la posición actual de los usuarios en un mapa utilizando ItemizedOverylay. Como la posición de los usuarios cambia regularmente, configuré CountDownTimer para eliminar el Itemizedoverlay actual y agregar uno nuevo en la nueva posición cada 5 segundos (no hay forma de cambiar la posición de un itemizedOverlay) pero la pantalla no está dibujando el ¡nuevas posiciones a menos que toque físicamente la pantalla! Aquí está el código de mi superposición detallada:Redibujar/actualizar Itemizedoverlay? (android/google maps api)

import java.util.ArrayList; 
import java.util.List; 

import android.app.AlertDialog; 
import android.content.Context; 
import android.graphics.drawable.Drawable; 
import android.widget.Toast; 

import com.google.android.maps.ItemizedOverlay; 
import com.google.android.maps.OverlayItem; 

public class HelloItemizedOverlay extends ItemizedOverlay{ 
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>(); 
Context mContext; 

public HelloItemizedOverlay(Drawable defaultMarker) { 
    /*This passes the defaultMarker up to the default constructor 
    * to bound its coordinates and then initialize mContext with the given Context.*/ 
    super(boundCenterBottom(defaultMarker)); 
} 
public HelloItemizedOverlay(Drawable defaultMarker, Context context) { 
    /*This passes the defaultMarker up to the default constructor 
    * to bound its coordinates and then initialize mContext with the given Context.*/ 
    super(boundCenterBottom(defaultMarker)); 
     mContext = context; 
} 
@Override 
protected boolean onTap(int index) { 
/*This uses the member android.content.Context to create 
* a new AlertDialog.Builder and uses the tapped OverlayItem's title 
* and snippet for the dialog's title and message text. (You'll see the 
* OverlayItem title and snippet defined when you create it below.)*/ 

    OverlayItem item = mOverlays.get(index); 
    AlertDialog.Builder dialog = new AlertDialog.Builder(mContext); 
    dialog.setTitle(item.getTitle()); 
    dialog.setMessage(item.getSnippet()); 
    dialog.show(); 
    return true; 
} 
public void addOverlay(OverlayItem overlay) { 
    mOverlays.add(overlay); 
    /*Each time you add a new OverlayItem to the ArrayList, you must 
    * call populate() for the ItemizedOverlay, which will read each 
    * of the OverlayItems and prepare them to be drawn.*/ 
    populate(); 
} 
public void addOverlayList(List<OverlayItem> overlayitems) { 
    Object temp[] = overlayitems.toArray(); 
    try{ 
     for(int i = 0;i<temp.length;i++) 
     { 
      mOverlays.add((OverlayItem)temp[i]); 
     } 
    }catch(Error e) 
    { 
     Toast.makeText(mContext, "Something happened when adding the overlays:"+e.getMessage() , 
       Toast.LENGTH_LONG).show(); 
    } 

    populate(); 
} 
public void removeOverlayList(List<OverlayItem> overlayitems) { 
    Object temp[] = overlayitems.toArray(); 
    try{ 
     for(int i = 0;i<temp.length;i++) 
     { 
      mOverlays.remove((OverlayItem)temp[i]); 
     } 
    }catch(Error e) 
    { 
     Toast.makeText(mContext, "Something happened when adding the overlays:"+e.getMessage() , 
       Toast.LENGTH_LONG).show(); 
    } 

    populate(); 
} 
public void removeOverlay(OverlayItem overlay){ 
    mOverlays.remove(overlay); 
    populate(); 
} 
public void doPopulate() 
{ 
    populate(); 
} 

@Override 
protected OverlayItem createItem(int i) { 
    // TODO Auto-generated method stub 
    return mOverlays.get(i); 
} 

@Override 
public int size() { 
    /*You must also override the size() method to return the current 
    * number of items in the ArrayList:*/ 
    return mOverlays.size(); 
} 

} 

¿Alguien sabe si hay un método o algo que pueda llamar para forzar un redibujo/refrescar cuando puse los nuevos artículos en?

EDIT: Aquí hay un fragmento de la MapsActivity:

public class HelloGoogleMaps extends MapActivity { 

/*************************** 
* map stuff 
*****/ 


HelloItemizedOverlay myPosition; 
MapView mapView; 
MapController mapController; 
List<Overlay> mapOverlays; 

OverlayItem myPositionOverlayItem; 

public double myLatitude = 0; 
public double myLongitude = 0; 
public double myCoarseLatitude = 0; 
public double myCoarseLongitude = 0; 

public boolean isGPS; 
public boolean isGPSFix; 
public boolean useGPSLocation; 
public boolean useNetworkLocation; 

public long mLastLocationMillis;//system time of last gps contact 
/*boolean so when gps gets your location it will zoom to where you are, 
* but will only do this once (once it's set to true)*/ 
boolean pickedUpLocation; 

public MyCount counter;//for timing events 


/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.mymapview); 
    pickedUpLocation = false; 



    mapView = (MapView) findViewById(R.id.mapview); 
    mapView.setBuiltInZoomControls(true); 
    mapView.setStreetView(true); 
    /*mapcontroller controls zoom etc*/ 
    mapController = mapView.getController(); 

    mapOverlays = mapView.getOverlays(); 
    Drawable my_icon = this.getResources().getDrawable(R.drawable.androidmarker_teacher); 
    myPosition = new HelloItemizedOverlay(my_icon, this); 
    itemizedoverlay = new HelloItemizedOverlay(drawable, this); 
    /*All overlay elements on a map are held by the MapView, so when you 
    * want to add some, you have to get a list from the getOverlays() method. 
    * Then instantiate the Drawable used for the map marker, which was saved in 
    * the res/drawable/ directory. The constructor for HelloItemizedOverlay 
    * (your custom ItemizedOverlay) takes the Drawable in order to set the 
    * default marker for all overlay items.*/ 

    /*Initialise GPS*/ 
    try{ 
    LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); 

    LocationListener mlocListener = new MyLocationListener(); 
    //get fine location 
    mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener); 
    //get coarse location 
    mlocManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mlocListener); 
    boolean isGPS = mlocManager.isProviderEnabled (LocationManager.GPS_PROVIDER); 
    MyGPSListener myGPSListener = new MyGPSListener(); 
    mlocManager.addGpsStatusListener(myGPSListener); 
    } 
    catch(Error e) 
    { 
     Toast.makeText(getApplicationContext(),"Error!"+e.getMessage(),Toast.LENGTH_SHORT).show(); 
    } 


    GeoPoint point = new GeoPoint((int)(myCoarseLatitude * 1e6),(int) (myCoarseLongitude* 1e6)); 
    myPositionOverlayItem = new OverlayItem(point, "Evening guvna!", "This is where i am"); 



    /*All that's left is to add this OverlayItem to your collection in the 
    * HelloItemizedOverlay instance, then add the HelloItemizedOverlay to the MapView: */ 
    myPosition.addOverlay(myPositionOverlayItem); 
    mapOverlays.add(myPosition); 
    /*begin counting 5 seconds to update positions*/ 
    counter = new MyCount(5000,1000); 
    counter.start(); 
} 

@Override 
protected boolean isRouteDisplayed() { 
    // TODO Auto-generated method stub 
    return false; 
} 
public void updateMyPosition() 
{ 
    /*remove my guy*/ 
    mapView.getOverlays().remove(myPosition); 
    myPosition.removeOverlay(myPositionOverlayItem); 
    myPosition.doPopulate(); 

    GeoPoint point; 
    if(useGPSLocation) 
    { 
     point = new GeoPoint((int)(myLatitude * 1e6),(int) (myLongitude* 1e6)); 
    } 
    else 
    { 
     point = new GeoPoint((int)(myCoarseLatitude * 1e6),(int) (myCoarseLongitude* 1e6)); 
    } 


    myPositionOverlayItem = new OverlayItem(point, "You are here", "Awww yeah!"); 
    myPosition.addOverlay(myPositionOverlayItem); 
    myPosition.doPopulate(); 
    mapOverlays.add(myPosition); 
} 

public void clearTheMap() 
{ 
    mapView.getOverlays().clear(); 
    myPosition.doPopulate(); 
} 


/******************************************************* 
* GPS!!!!!!!! 
* This method gets the location of you from gps 
* ************************************************/ 
public class MyLocationListener implements LocationListener 
{ 

    public void onLocationChanged(Location loc) 
    { 
     String provider = loc.getProvider(); 
     if(provider.equals(LocationManager.GPS_PROVIDER)) 
     { 
      myLatitude = loc.getLatitude(); 
      myLongitude = loc.getLongitude(); 
      mLastLocationMillis = SystemClock.elapsedRealtime(); 
      if((!pickedUpLocation)&&(myLatitude!=0)) 
      { 
       mapController.animateTo(new GeoPoint((int)(myLatitude * 1e6),(int) (myLongitude* 1e6))); 
       pickedUpLocation = true; 
      } 
     } 
     else 
     { 
      myCoarseLatitude = loc.getLatitude(); 
      myCoarseLongitude = loc.getLongitude(); 
      if((!pickedUpLocation)&&(myCoarseLatitude!=0)) 
      { 
       //Toast.makeText(getBaseContext(), "picked up Location with network - "+myCoarseLatitude+" "+myCoarseLongitude, Toast.LENGTH_LONG).show(); 
       mapController.animateTo(new GeoPoint((int)(myCoarseLatitude * 1e6),(int) (myCoarseLongitude* 1e6))); 
       pickedUpLocation = true; 
      } 
     } 

     /*first time it picks up your location it will animate to where you are*/ 


     /* 
     String Text = "My current location is: "+ 
     "Latitud = " + loc.getLatitude()+ 
     "Longitud = " + loc.getLongitude(); 

     Toast.makeText(getApplicationContext(),Text,Toast.LENGTH_SHORT).show(); 
     */ 
    } 

    public void onProviderDisabled(String provider) 
    { 
     Toast.makeText(getApplicationContext(),"Gps Disabled",Toast.LENGTH_SHORT).show(); 
     myLatitude = -1; 
     myLongitude = -1; 
    } 
    public void onProviderEnabled(String provider) 
    { 
     Toast.makeText(getApplicationContext(),"Gps Enabled",Toast.LENGTH_SHORT).show(); 
     myLatitude = 0; 
     myLongitude = 0; 
    } 

    public void onStatusChanged(String provider, int status, Bundle extras) 
    { 

    } 
} 

/*********************************************** 
* -GPS Status monitor- 
* Will see if the sattelites are still fixed to your phone 
* If satellites arent available, it takes network (coarse) location 
* If a fix is aquired it will use GPS (fine) location 
* **********************************/ 
private class MyGPSListener implements GpsStatus.Listener { 
    public void onGpsStatusChanged(int event) { 
     switch (event) { 
      case GpsStatus.GPS_EVENT_SATELLITE_STATUS: 
       if (myLatitude != 0) 
        isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000; 

       if (isGPSFix) { // A fix has been acquired. 
        useGPSLocation = true; 
        useNetworkLocation = false; 
       } else { // The fix has been lost. 
        useGPSLocation = false; 
        useNetworkLocation = true; 
       } 

       break; 
      case GpsStatus.GPS_EVENT_FIRST_FIX: 
       // Do something. 
       isGPSFix = true; 
       useGPSLocation = true; 
        useNetworkLocation = false; 
       break; 
     } 
    } 
} 

/************************************************************* 
* Counter class for timing events 
**********/ 
public class MyCount extends CountDownTimer{ 

    public MyCount(long millisInFuture, long countDownInterval) { 
    super(millisInFuture, countDownInterval); 
    } 

    @Override 
    public void onFinish() { 
     clearTheMap(); 
     updateMyPosition();//redraw my guy 
     myPosition.doPopulate(); 

     //Toast.makeText(getApplicationContext(),"Sent my position - used ",Toast.LENGTH_SHORT).show(); 
     resetTimer(); 
    } 

    public void resetTimer() 
    { 
     counter = new MyCount(5000,1000); 
     counter.start(); 
    } 

    @Override 
    public void onTick(long millisUntilFinished) { 
    /*tv.setText(”Left: ” + millisUntilFinished/1000);*/ 

    } 

    } 
} 

Respuesta

18

Uso mapview.invalidate(). Esto eventualmente causará un redibujado.

+1

Acabo de probarlo, parece estar haciendo el truco :) muchas gracias por esto! – AndroidNoob

2

use mapView.removeAllViewsInLayout(); Está funcionando para mí.