Sobreposições de blocos

Uma sobreposição de blocos, geralmente chamada de camada de blocos, é uma coleção de imagens exibida sobre os blocos do Mapa básico.

Exemplos de código

O repositório ApiDemos no GitHub inclui um exemplo que demonstra o recurso de sobreposição de blocos:

Introdução

Uma TileOverlay define um conjunto de imagens adicionadas sobre os blocos do Mapa básico.

É necessário fornecer os blocos para cada nível de zoom que você pretende oferecer. Se você tiver blocos suficientes em diversos níveis de zoom, poderá complementar os dados do mapa do Google para o mapa completo.

As sobreposições de blocos são úteis para adicionar várias imagens ao mapa e cobrir áreas geográficas amplas. Enquanto isso, as sobreposições de solo são uma ótima maneira de corrigir uma única imagem em uma área do mapa.

As sobreposições de blocos transparentes podem ser usadas para adicionar recursos ao mapa, definindo programaticamente um fator de transparência da sobreposição de blocos ou fornecendo imagens de blocos transparentes.

Coordenadas e níveis de zoom de blocos

A API Google Maps divide as imagens de cada nível de zoom em um conjunto de blocos de mapa quadrados, organizados em uma grade. Quando um mapa muda para uma nova localização ou um novo nível de zoom, a API Maps determina quais blocos são necessários e converte essa informação em um conjunto de blocos a recuperar.

O bloco com as coordenadas (0,0) está sempre no canto noroeste do mapa, com os valores de X aumentando de oeste para leste e os valores de Y aumentando de norte para sul. Os blocos são indexados usando as coordenadas X, Y daquela origem.

No nível de zoom 0, o mundo inteiro é renderizado em um único bloco. Cada nível de zoom aumenta a ampliação por um fator de dois. Portanto, no nível de zoom 1, o mapa é renderizado como uma grade de blocos de 2 x 2. No nível 2, a grade é de 4 x 4. No nível 3, a grade é de 8 x 8, e assim por diante.

Por exemplo, no nível de zoom 2, o planeta é dividido em 16 blocos. Cada bloco pode ser referenciado por uma combinação exclusiva de X, Y e zoom:

Ao criar imagens para uma camada de blocos, é preciso criar uma imagem para cada bloco em cada nível de zoom que você pretende oferecer. Ao exibir blocos, o Google Maps tenta exibir 256 dp (pixels independentes de dispositivo). Para dispositivos de alta resolução, recomendamos retornar blocos com dpi alto (512 x 512 px). Consulte a documentação para desenvolvedores Android se quiser informações sobre como oferecer compatibilidade com diferentes tamanhos e densidades de tela.

Observação: os níveis de zoom permitidos pela câmera dependem de diversos fatores e não estão relacionados aos níveis de zoom suportados pelos seus blocos.

  1. GoogleMap.getMaxZoomLevel() retorna o nível de zoom máximo disponível na posição atual da câmera. Esse valor considera o tipo de mapa usado no momento. Por exemplo, um mapa de satélite ou de terreno pode ter um nível de zoom máximo menor que os blocos do Mapa básico.
  2. GoogleMap.getMinZoomLevel() retorna o nível de zoom mínimo, que é o mesmo para todos os locais (ao contrário do nível de zoom máximo), mas pode variar entre dispositivos e tamanhos de mapa.

Adicionar uma sobreposição de blocos

A forma mais simples e comum de criar uma sobreposição de blocos é fornecer um URL apontando para a imagem de bloco relevante. UrlTileProvider é uma implementação parcial de TileProvider que fornece blocos de imagem com base em um URL. Essa classe exige que todas as imagens tenham as mesmas dimensões.

É necessário implementar UrlTileProvider.getTileUrl(), que aceita as coordenadas do bloco (X, Y, zoom) e retorna um URL que aponta para a imagem a ser usada no bloco. O método retornará nulo se não existir um bloco para as coordenadas X, Y e zoom informadas. Um URL pode apontar para um recurso da Web, um material Android ou um arquivo no disco local.

Configure um repositório de imagens de bloco em um servidor, definidas para todas as coordenadas X e Y e todos os níveis de zoom que você pretende oferecer. Depois, adicione a sobreposição de blocos:

  1. Defina um UrlTileProvider para fornecer as imagens de bloco.
  2. Substitua getTileUrl() para construir o URL de cada imagem de bloco.
  3. Forneça um objeto TileOverlayOptions com as opções relevantes:
    • fadeIn: booleano. Especifica se os blocos aparecerão gradualmente. O valor padrão é true. Desative a exibição gradual para alternar rapidamente entre as sobreposições de blocos. Para ver as informações sobre a relação entre transparência e exibição gradual, consulte a seção sobre transparência abaixo.
    • tileProvider: o TileProvider que será usado na sobreposição.
    • transparency: valor flutuante. Define um fator de transparência para imagens de bloco. O valor precisa estar no intervalo [0.0f, 1.0f], em que 0.0f significa totalmente opaco (padrão) e 1.0f significa totalmente transparente. Consulte a seção sobre transparência abaixo para ver um exemplo de código e a relação entre transparência e exibição gradual.
    • visible: booleano. Especifica a visibilidade da sobreposição dos blocos. Uma sobreposição de blocos invisível (valor false) não é desenhada no mapa, mas mantém todas as propriedades. O padrão é true.
    • zIndex: determina a ordem em que a sobreposição dos blocos será desenhada em relação a outras sobreposições, incluindo sobreposições de solo, círculos, polilinhas e polígonos. As sobreposições com um Z-index mais alto são desenhadas sobre aquelas que têm um Z-index mais baixo. A ordem das sobreposições que têm o mesmo Z-index é aleatória. O valor padrão do Z-index é 0. Os marcadores são sempre desenhados sobre as outras sobreposições, independentemente do Z-index delas.
  4. Chame GoogleMap.addTileOverlay() para adicionar a sobreposição ao mapa.

Java

private GoogleMap map;

TileProvider tileProvider = new UrlTileProvider(256, 256) {

    @Override
    public URL getTileUrl(int x, int y, int zoom) {

        /* Define the URL pattern for the tile images */
        String s = String.format("http://my.image.server/images/%d/%d/%d.png", zoom, x, y);

        if (!checkTileExists(x, y, zoom)) {
            return null;
        }

        try {
            return new URL(s);
        } catch (MalformedURLException e) {
            throw new AssertionError(e);
        }
    }

    /*
     * Check that the tile server supports the requested x, y and zoom.
     * Complete this stub according to the tile range you support.
     * If you support a limited range of tiles at different zoom levels, then you
     * need to define the supported x, y range at each zoom level.
     */
    private boolean checkTileExists(int x, int y, int zoom) {
        int minZoom = 12;
        int maxZoom = 16;

        return (zoom >= minZoom && zoom <= maxZoom);
    }
};

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

Kotlin

private lateinit var map: GoogleMap

var tileProvider: TileProvider = object : UrlTileProvider(256, 256) {
    override fun getTileUrl(x: Int, y: Int, zoom: Int): URL? {

        /* Define the URL pattern for the tile images */
        val url = "http://my.image.server/images/$zoom/$x/$y.png"
        return if (!checkTileExists(x, y, zoom)) {
            null
        } else try {
            URL(url)
        } catch (e: MalformedURLException) {
            throw AssertionError(e)
        }
    }

    /*
     * Check that the tile server supports the requested x, y and zoom.
     * Complete this stub according to the tile range you support.
     * If you support a limited range of tiles at different zoom levels, then you
     * need to define the supported x, y range at each zoom level.
     */
    private fun checkTileExists(x: Int, y: Int, zoom: Int): Boolean {
        val minZoom = 12
        val maxZoom = 16
        return zoom in minZoom..maxZoom
    }
}

val tileOverlay = map.addTileOverlay(
    TileOverlayOptions()
        .tileProvider(tileProvider)
)
      

Para ver um exemplo de UrlTileProvider em ação, consulte TileOverlayDemoActivity no exemplo de código que acompanha o SDK do Google Play Services.

Definir transparência para sobreposições de blocos

Pode ser útil sobrepor blocos transparentes no mapa para que os usuários vejam o mapa abaixo dos blocos sobrepostos. Faça isso fornecendo seus próprios blocos transparentes ou definindo programaticamente um fator de transparência da sobreposição de blocos.

O exemplo de código a seguir alterna a transparência da sobreposição de blocos entre 0.5f e 0.0f:

Java

private TileOverlay tileOverlayTransparent;

@Override
public void onMapReady(GoogleMap map) {
    tileOverlayTransparent = map.addTileOverlay(new TileOverlayOptions()
        .tileProvider(new UrlTileProvider(256, 256) {
            // ...
        })
        .transparency(0.5f));
}

// Switch between 0.0f and 0.5f transparency.
public void toggleTileOverlayTransparency() {
    if (tileOverlayTransparent != null) {
        tileOverlayTransparent.setTransparency(0.5f - tileOverlayTransparent.getTransparency());
    }
}
      

Kotlin

private var tileOverlayTransparent: TileOverlay? = null

override fun onMapReady(map: GoogleMap) {
    tileOverlayTransparent = map.addTileOverlay(
        TileOverlayOptions()
            .tileProvider(object : UrlTileProvider(256, 256) {
                // ...
            })
            .transparency(0.5f)
    )
}

// Switch between 0.0f and 0.5f transparency.
fun toggleTileOverlayTransparency() {
    tileOverlayTransparent?.let {
        it.transparency = 0.5f - it.transparency
    }
}
      

A transparência é implementada como multiplicador de canal alfa para imagens de blocos. Para definir a transparência de uma sobreposição de blocos, forneça um objeto TileOverlayOptions com uma transparency no intervalo [0.0f, 1.0f], conforme o exemplo acima. Um valor de 0.0f significa que a sobreposição de blocos é totalmente opaca, e 1.0f significa que ela é totalmente transparente. O valor padrão é 0.0f (opaca).

É possível acessar a transparência da sobreposição de blocos chamando TileOverlay.getTransparency(). Para mudá-la, chame TileOverlay.setTransparency().

Transparência, animação e exibição gradual

Não há animação quando a transparência é alterada. A opção de transparência opera junto com a fadeIn.

A exibição gradual oferece animação de transparência no carregamento do bloco. Se você definir um valor de transparência, os blocos serão exibidos gradualmente, de totalmente transparentes até o valor definido. Se você alterar a transparência durante a exibição gradual, a animação continuará até a nova transparência desejada.

Remover uma sobreposição de blocos

É possível remover uma sobreposição de blocos com o método TileOverlay.remove().

Java

tileOverlay.remove();
      

Kotlin

tileOverlay.remove()
      

Limpar blocos desatualizados

Se os blocos fornecidos pela sobreposição ficarem "desatualizados", chame clearTileCache() para forçar uma atualização. Como resultado, todos os blocos da sobreposição serão recarregados. Por exemplo, se os blocos fornecidos pelo TileProvider mudarem, chame clearTileCache() depois, para garantir que os blocos anteriores não sejam mais renderizados.

Java

tileOverlay.clearTileCache();
      

Kotlin

tileOverlay.clearTileCache()