2015-11-02 27 views
11

Cerco di mettere uno sfondo tra la mappa e il mio marcatore; questa immagine dovrebbe sempre (!) stare dietro a tutti i marcatori.Android Google Maps - sfondo personalizzato dietro tutti i marcatori

Ho provato in diversi modi, ad es. showInfoWindow() su tutti i miei marcatori eccetto l'immagine di sfondo, ma sembra che questo sarebbe utile solo per l'ultimo.

Quindi ho provato una soluzione utilizzando GroundOverlay, ma ho bisogno che la mia immagine rimanga sempre delle stesse dimensioni (ad esempio metà della dimensione del dispositivo), indipendentemente dal fattore di zoom.

Esiste una soluzione su Android per questo?

+0

Perché non si imposta semplicemente un'icona personalizzata per gli indicatori? Avere un numero elevato di Marker e GroundOverlay nella tua mappa influisce sulle prestazioni, quindi cercherò di non impostare un Marker e un GroundOverlay dove ci dovrebbe essere solo un Marker – antonio

+0

Ho delle icone personalizzate per i miei marcatori, ma ci dovrebbe essere UNO che io sto usando come sfondo; non è possibile quando si usano gli indicatori dato che non riesco a configurare uno z-index – swalkner

+0

OK, scusa, non ho capito la tua domanda – antonio

risposta

-1

L'opzione migliore è utilizzare uno GroundOverlay per mostrare lo sfondo, aggiungerlo e rimuoverlo quando la vista cambia e calcolare le sue dimensioni in base allo VisibleRegion della mappa in modo che mantenga la dimensione corretta tra gli zoom.

Da the documentation:

Posizione

Ci sono due modi per specificare la posizione della sovrapposizione terra:

  • Usando una posizione: è necessario fornire un'immagine di la sovrapposizione a terra, un LatLng a cui verrà fissata l'ancora e la larghezza della sovrapposizione (in metri). L'ancoraggio è, per impostazione predefinita, 50% dalla parte superiore dell'immagine e 50% dalla parte sinistra dell'immagine. Questo può essere cambiato. Opzionalmente è possibile fornire l'altezza della sovrapposizione (in metri). Se non si fornisce l'altezza della sovrapposizione, verrà automaticamente calcolata per preservare le proporzioni dell'immagine.

  • Utilizzo di un limite: è necessario fornire un LatLngBounds che conterrà l'immagine.

Il seguente esempio utilizza un OnCameraChangeListener rimuovere e aggiungere un GroundOverlay che mostra il ic_launcher drawable nel centro della mappa, 75% della larghezza della carta (Rimozione e aggiunta la GroundOverlay sul onCameraChange evento assicura che la dimensione dell'immagine sia sempre la stessa indipendentemente dal livello di zoom).

public class MyMapActivity extends Activity implements OnCameraChangeListener { 
    GroundOverlay backgroundOverlay = null; 
    GoogleMap map; 

    // ... 

    @Override 
    public void onCameraChange(final CameraPosition cameraPosition) { 
     if (backgroundOverlay != null) { 
      backgroundOverlay.remove(); 
     } 

     VisibleRegion visibleRegion = map.getProjection() 
       .getVisibleRegion(); 

     Location nearLeftLocation = new Location("nearLeftLocation"); 
     nearLeftLocation.setLatitude(visibleRegion.nearLeft.latitude); 
     nearLeftLocation.setLongitude(visibleRegion.nearLeft.longitude); 

     Location nearRightLocation = new Location("nearRightLocation"); 
     nearRightLocation.setLatitude(visibleRegion.nearRight.latitude); 
     nearRightLocation.setLongitude(visibleRegion.nearRight.longitude); 

     float width = nearLeftLocation.distanceTo(nearRightLocation); 

     GroundOverlayOptions background = new GroundOverlayOptions() 
       .image(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)) 
       .position(cameraPosition.target, width * 0.75f); 

     backgroundOverlay = map.addGroundOverlay(background); 
    } 
} 

UPDATE:

Come dico nei commenti possiamo e setDimensions sulla esistente GroundOverlay invece di aggiungere/rimuovere su ogni cambiamento della macchina fotografica.

L'ho provato su diversi dispositivi e sembra ridurre lo sfarfallio dei dispositivi di fascia bassa, ma non è ancora una soluzione perfetta (l'immagine si ridimensiona tra gli zoom). Sono abbastanza sicuro che questo è il meglio che possiamo ottenere usando GroundOverlay s.

public class MyMapActivity extends Activity implements OnCameraChangeListener { 
    GroundOverlay backgroundOverlay = null; 
    GoogleMap map; 

    // ... 

    @Override 
    public void onCameraChange(final CameraPosition cameraPosition) { 
     VisibleRegion visibleRegion = map.getProjection().getVisibleRegion(); 

     Location nearLeftLocation = new Location("nearLeftLocation"); 
     nearLeftLocation.setLatitude(visibleRegion.nearLeft.latitude); 
     nearLeftLocation.setLongitude(visibleRegion.nearLeft.longitude); 

     Location nearRightLocation = new Location("nearRightLocation"); 
     nearRightLocation.setLatitude(visibleRegion.nearRight.latitude); 
     nearRightLocation.setLongitude(visibleRegion.nearRight.longitude); 

     float width = nearLeftLocation.distanceTo(nearRightLocation); 

     if (backgroundOverlay == null) { 
      GroundOverlayOptions background = new GroundOverlayOptions() 
        .image(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)) 
        .position(cameraPosition.target, width * 0.75f); 

      backgroundOverlay = map.addGroundOverlay(background); 
     } else { 
      backgroundOverlay.setPosition(cameraPosition.target); 
      backgroundOverlay.setDimensions(width * 0.75f); 
     } 
    } 
} 

UPDATE

ho trovato un'altra soluzione.Se lo sfondo è un colore semplice, semitrasparente, puoi utilizzare TileOverlay per impostarlo sotto tutti i marker.

L'idea è di creare un TileProvider che restituisca sempre un'immagine molto piccola (2x2 pixel nel mio esempio) che verrà disegnata sotto tutti i tuoi marcatori. Per garantire prestazioni, lo Tile restituito dallo TileProvider sarà sempre lo stesso.

Ecco il codice:

public class BackgroundTileProvider implements TileProvider { 
    private Tile tile; 

    @Override 
    public Tile getTile(int x, int y, int zoom) { 
     if (tile == null) { 
      // Create a very small (for performance) bitmap with alpha 
      Bitmap bmp = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888); 

      // Draw the desired color to use as background 
      Canvas canvas = new Canvas(bmp); 
      canvas.drawColor(Color.argb(150, 255, 0, 0)); 

      // Get the bytes and create the Tile 
      ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
      bmp.compress(Bitmap.CompressFormat.PNG, 100, stream); 

      tile = new Tile(2, 2, stream.toByteArray()); 
     } 

     return tile; 
    } 
} 

Sarà necessario aggiungere il TileOverlay alla mappa come segue:

TileProvider tileProvider = new BackgroundTileProvider(); 
TileOverlay tileOverlay = map.addTileOverlay(
    new TileOverlayOptions().tileProvider(tileProvider)); 

Il risultato sarà simile a questa:

enter image description here

+1

grazie mille, attualmente è la soluzione più promettente, purtroppo l'immagine è nascosta durante i cambi di zoom; Lampeggia molto a causa della rimozione/aggiunta, puoi pensare a una soluzione come renderla più fluida? – swalkner

+1

Puoi provare a 'setPosition' e' setDimensions' sull'esistente 'GroundOverlay' invece di aggiungerlo/rimuoverlo su ogni cambio di telecamera, ma non ti libererai dei problemi che dici. Comprendo che vorresti lo sfondo per "seguire" i movimenti della tua videocamera, ma visti gli eventi esposti dall'API di Google Maps (https://developers.google.com/maps/documentation/android-api/events) e le tue esigenze (hai bisogno dello sfondo per posare sotto i tuoi pennarelli) questa è la soluzione migliore a cui possa pensare. Forse un altro sviluppatore può dare una risposta migliore ... – antonio

+0

Potrebbe @downvoter spiegare per favore? – antonio

0

Si può provare questo, calcolare il dimensio on in base allo fattore di zoom e applicare tali dimensioni allo GroundOverlay.

float zoomLevel=mMap.getCameraPosition().zoom; 
    //calculate meters*********************   
    myBounds = mMap.getProjection().getVisibleRegion().latLngBounds; 
    myCenter= mMap.getCameraPosition().target; 
    if (myCenter.latitude==0 || myCenter.longitude==0) { 
     myCenter=new LatLng(myLocation.getLatitude(),myLocation.getLongitude()); 
    } 

    LatLng ne = myBounds.northeast; 

    // r = radius of the earth in statute miles 
    double r = 3963.0; 

    // Convert lat or lng from decimal degrees into radians (divide by 57.2958) 
    double lat1 = myCenter.latitude/57.2958; 
    double lon1 = myCenter.longitude/57.2958; 
    final double lat2 = ne.latitude/57.2958; 
    final double lon2 = ne.longitude/57.2958; 

    // distance = circle radius from center to Northeast corner of bounds 
    double dis = r * Math.acos(Math.sin(lat1) * Math.sin(lat2) + 
     Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1)); 

    //1 Meter = 0.000621371192237334 Miles 
    double meters_calc=dis/0.000621371192237334; 

    float factor=1; 
    if (zoomLevel==15) { // my default zoom level yours can be different 
     metersoverlay=meters_calc; // global variable metersoverlay set 
    } 
    else { // if my zoom level change then I have to calculate dimension scale factor 
     factor=(float) (meters_calc/metersoverlay); 
    } 

    //******************************* now we are ready to set dimension of background overlay 
    float dimensions=1000*factor; 
    loadingGroundOverlayBg.setDimensions(dimensions); 
+0

dove lo inseriresti? In "' 'onCameraChange-Listener'''? E come creare loadingGroundOverlay - come descritto da @antonio? – swalkner

+0

sì puoi metterlo in 'onCameraChanged' e vedere se funziona e' loadingGroundOverlayBg' è il nome oggetto di 'GroundOverlay' –

+0

un non c'è bisogno di aggiungere/rimuovere la sovrapposizione ogni volta sulla fotocamera cambia come detto @antonio, solo setDimensions lo farà. –

5

Questo è facile da fare.

Aggiungere due marcatori invece di uno. Per prima cosa aggiungi lo sfondo come bitmap su lat_lng.

Qualcosa di simile a questo:

map.addMarker(new MarkerOptions() 
     .position(lat_lng) 
     .anchor(0.5f, 0.5f) 
     .icon(BitmapDescriptorFactory.fromBitmap(bitmap))); 

Allora aggiungi la tua marcatore come si fa normalmente allo stesso lat_lng.

Esegui quanto sopra per ciascuno dei tuoi segnalini.

+1

Suppongo di non averlo capito; lo sfondo dovrebbe sempre coprire l'intera mappa e non è un'immagine solida ma sembra un radar, quindi non posso aggiungerlo più volte e posizioni diverse – swalkner

Problemi correlati