Os mapas no SDK do Maps para Android podem ser inclinados e girados com gestos fáceis. Assim, os usuários podem ajustar na orientação que preferirem. Em qualquer nível de zoom, é possível movimentar o mapa ou mudar a perspectiva com pouquíssima latência, graças ao volume reduzido de blocos com base em vetores do mapa.
Exemplos de código
O repositório ApiDemos (link em inglês) no GitHub inclui um exemplo que demonstra os recursos da câmera:
- CameraDemoActivity – Kotlin: como alterar a posição da câmera
- CameraDemoActivity – Java: como alterar a posição da câmera
Introdução
Assim como o Google Maps na Web, o SDK do Google Maps para Android representa a superfície do mundo (uma esfera) na tela do seu dispositivo (uma superfície plana), utilizando a projeção de Mercator. Nas direções Leste e Oeste, o mapa é repetido infinitamente à medida que o mundo se integra perfeitamente ao redor de si mesmo. Nas direções Norte e Sul, o mapa é limitado a aproximadamente 85 graus ao Norte e 85 graus ao Sul.
Observação: uma projeção de Mercator tem uma largura longitudinal finita e uma altura latitudinal infinita. Nós "cortamos" as imagens de Mapas básicos usando a projeção de Mercator em aproximadamente +/- 85 graus para que o formato resultante do mapa seja quadrado, o que proporciona uma lógica mais fácil para a seleção de blocos.
Com o SDK do Maps para Android, é possível alterar o ponto de vista do usuário do mapa modificando a câmera.
As mudanças da câmera não alteram marcadores, sobreposições ou outros elementos gráficos adicionados, embora você possa mudar suas adições para que se adequem melhor à nova visualização.
Como você pode detectar os gestos do usuário no mapa, é possível mudar o mapa em resposta aos pedidos do usuário. Por exemplo, o método de callback OnMapClickListener.onMapClick()
responde a um único toque no mapa. Como o método recebe a latitude e longitude do local do toque, você pode responder movimentando ou aplicando zoom a esse ponto.
Métodos semelhantes estão disponíveis para responder aos toques no balão de um marcador ou para responder a um gesto de arrastar em um marcador.
Você também pode detectar os movimentos da câmera para que o app receba uma notificação quando a câmera começar a se mover, estiver se movendo ou interromper o movimento. Para mais detalhes, consulte o guia sobre eventos de mudança da câmera.
A posição da câmera
A visualização de mapa é modelada como uma câmera apontada para um plano nivelado. A posição da câmera, e, consequentemente, a renderização do mapa, é especificada pelas seguintes propriedades: alvo (localização de latitude/longitude), rolamento, inclinação e zoom.
Alvo (local)
O alvo da câmera é o local do centro do mapa, especificado como coordenadas de latitude e longitude.
A latitude pode variar entre -85 e 85 graus, inclusive. Valores acima ou abaixo desse intervalo são fixados para o valor mais próximo dentro desse intervalo. Por exemplo, uma latitude especificada como 100 terá o valor de 85. A longitude varia entre -180 e 180 graus. Valores acima ou abaixo desse intervalo são alterados para se adequarem ao intervalo (-180, 180). Por exemplo, 480, 840 e 1200 serão alterados para 120 graus.Rolamento (orientação)
O rolamento da câmera especifica a direção da bússola, medida em graus a partir do norte verdadeiro, correspondendo à borda superior do mapa. Se você desenhar uma linha vertical do centro do mapa para a borda superior, o rolamento corresponde à direção da câmera (medida em graus) em relação ao Norte verdadeiro.
Um rolamento de 0 significa que a parte superior do mapa aponta para o Norte verdadeiro. O valor de 90 graus significa que a parte superior do mapa aponta para o Leste (90 graus em uma bússola). Um valor de 180 significa que a parte superior do mapa aponta para o Sul.
Com a API Maps você pode alterar o rolamento de um mapa. Ao dirigir um carro, muitas vezes giramos um mapa de estradas para alinhá-lo com a direção da viagem, enquanto ao fazer uma trilha usando um mapa e uma bússola, geralmente orientamos o mapa para que a linha vertical aponte para o Norte.
Inclinação (ângulo de visão)
A inclinação define a posição da câmera em um arco diretamente sobre a posição central do mapa, medida em graus a partir do nadir (a direção que aponta diretamente abaixo da câmera). Um valor de 0 corresponde a uma câmera apontada para baixo. Valores maiores que 0 correspondem a uma câmera inclinada para o horizonte pelo número especificado de graus. Quando você muda o ângulo de visão, o mapa é apresentado em perspectiva, com elementos distantes aparecendo menores, e elementos próximos aparecendo maiores. Isso é ilustrado abaixo.
Nas imagens a seguir, o ângulo de visão é 0 grau. A primeira imagem mostra um esquema da situação. A posição 1 é a posição da câmera, e a posição 2 é a posição atual do mapa. O mapa resultante está abaixo.
Nas imagens abaixo, o ângulo de visão é de 45 graus. A câmera se move no meio do caminho ao longo de um arco, entre diretamente para cima (0 grau) e o solo (90 graus), para a posição 3. A câmera ainda está direcionada para o ponto central do mapa, mas agora a área representada pela linha na posição 4 está visível.
O mapa nesta captura de tela ainda está centralizado sobre o mesmo ponto do mapa original. No entanto, mais elementos apareceram na parte superior. À medida que você ultrapassa o ângulo de 45 graus, os elementos entre a câmera e a posição do mapa aparecem proporcionalmente maiores, enquanto os elementos que estão além da posição do mapa aparecem proporcionalmente menores, produzindo um efeito tridimensional.
Zoom
O nível de zoom da câmera determina a escala do mapa. Em níveis mais elevados de zoom, é possível ver mais detalhes na tela, enquanto em níveis de zoom menores, uma parte maior do mundo pode ser vista. Em um nível de zoom 0, a escala do mapa representa o mundo todo com uma largura de aproximadamente 256 dp (pixels de densidade independente).
Um aumento de zoom de 1 dobra a largura do mundo na tela. Portanto, com o nível de zoom em N, a largura do mundo é aproximadamente 256 x 2N dp. Por exemplo, no nível de zoom 2, o mundo todo tem aproximadamente 1.024 dp de largura.
O nível de zoom não precisa ser um número inteiro. A variação permitida pelo mapa depende de diversos fatores, incluindo destino, tipo de mapa e tamanho da tela. Qualquer número fora do intervalo será convertido para o valor válido mais próximo, que pode ser o nível de zoom mínimo ou máximo. A lista a seguir mostra o nível aproximado de detalhamento que você consegue ver em cada nível de zoom:
- 1: mundo
- 5: terra/continente
- 10: cidade
- 15: ruas
- 20: construções
Como mover a câmera
Com a API Maps, você pode alterar a parte do mundo visível no mapa. Isso é possível, alterando a posição da câmera (em oposição ao movimento do mapa).
Quando você movimenta a câmera, tem a opção de animar o movimento resultante dela. A animação alterna entre os atributos atuais e os novos atributos da câmera. Você também pode controlar a duração da animação.
Para mudar a posição da câmera, especifique para onde você quer movê-la, usando uma CameraUpdate
. Com a API Maps, você pode criar vários tipos diferentes de CameraUpdate
usando CameraUpdateFactory
. As seguintes opções estão disponíveis:
Alterar o nível de zoom e definir o mínimo e o máximo
CameraUpdateFactory.zoomIn()
e CameraUpdateFactory.zoomOut()
oferecem um CameraUpdate
que muda o nível de zoom em 1.0 sem afetar outras propriedades.
CameraUpdateFactory.zoomTo(float)
oferece um CameraUpdate
que muda o nível de zoom para o valor fornecido, mantendo todas as outras propriedades.
CameraUpdateFactory.zoomBy(float)
e CameraUpdateFactory.zoomBy(float, Point)
oferecem um CameraUpdate
que aumenta (ou diminui, se o valor for negativo) o nível de zoom pelo valor fornecido. O último corrige o ponto determinado na tela, de forma que ele permanece no mesmo local (latitude/longitude) e, assim, pode alterar o local da câmera para essa finalidade.
Pode ser útil definir um nível de zoom mínimo e/ou máximo preferido. Por exemplo, isso pode ajudar a experiência do usuário quando o app exibir uma área definida em volta de um ponto de interesse ou quando houver uma sobreposição de blocos personalizada com um conjunto limitado de níveis de zoom.
Kotlin
private lateinit var map: GoogleMap map.setMinZoomPreference(6.0f) map.setMaxZoomPreference(14.0f)
Java
private GoogleMap map; map.setMinZoomPreference(6.0f); map.setMaxZoomPreference(14.0f);
Há considerações técnicas que podem evitar que a API permita que os usuários aumentem ou diminuam muito o zoom. Por exemplo, um mapa de satélite ou de terreno pode ter um zoom máximo menor que os blocos do Mapa básico.
Como alterar a posição da câmera
Há dois métodos convenientes para as alterações comuns de posição.
CameraUpdateFactory.newLatLng(LatLng)
oferece um CameraUpdate
que muda a latitude e a longitude da câmera, preservando todas as outras propriedades.
CameraUpdateFactory.newLatLngZoom(LatLng, float)
oferece um CameraUpdate
que altera a latitude, a longitude e o zoom da câmera, preservando todas as outras propriedades.
Para ter flexibilidade total na alteração da posição da câmera, use CameraUpdateFactory.newCameraPosition(CameraPosition)
, que fornece um CameraUpdate
, movendo a câmera para a posição determinada. Um CameraPosition
pode ser obtido diretamente, usando new CameraPosition()
ou com um CameraPosition.Builder
usando new CameraPosition.Builder()
.
Movimento (rolagem)
CameraUpdateFactory.scrollBy(float, float)
oferece um CameraUpdate
que muda a latitude e longitude da câmera de modo que o mapa se mova pelo número especificado de pixels. Um valor X positivo move a câmera para a direita, fazendo com que o mapa pareça ser movido para a esquerda. Um valor Y positivo move a câmera para baixo, fazendo com que o mapa pareça ser movido para cima. Por outro lado, os valores negativos de X fazem a câmera se mover para a esquerda, de modo que o mapa pareça ter sido deslocado para a direita, enquanto valores negativos de Y fazem a câmera se mover para cima. A rolagem está relacionada à orientação atual da câmera. Por exemplo, se a câmera tem um rolamento de 90 graus, Leste será para "cima".
Como definir limites
Como definir os limites do mapa
Pode ser útil mover a câmera de maneira que uma área inteira de interesse fique visível no maior nível de zoom possível. Por exemplo, se você está exibindo todos os postos de gasolina em um raio de 5 km da posição atual do usuário, mova a câmera de modo que todos eles fiquem visíveis na tela. Para fazer isso, primeiro calcule os LatLngBounds
que você quer ver na tela. Você pode usar CameraUpdateFactory.newLatLngBounds(LatLngBounds bounds, int
padding)
para ter uma CameraUpdate
que altere a posição da câmera, de modo que os LatLngBounds
especificados se encaixem totalmente no mapa, considerando o preenchimento (em pixels) especificado. A CameraUpdate
retornada assegura que a lacuna (em pixels) entre os limites indicados e a borda do mapa seja pelo menos igual ao preenchimento especificado. A inclinação e o rolamento do mapa serão 0.
Kotlin
val australiaBounds = LatLngBounds( LatLng((-44.0), 113.0), // SW bounds LatLng((-10.0), 154.0) // NE bounds ) map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0))
Java
LatLngBounds australiaBounds = new LatLngBounds( new LatLng(-44, 113), // SW bounds new LatLng(-10, 154) // NE bounds ); map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0));
Centralizar o mapa em uma área
Em alguns casos, você precisa centralizar a câmera dentro dos limites, em vez de incluir as bordas extremas, por exemplo, para centralizar a câmera em um país, mantendo um zoom constante. Nesse caso, é possível usar um método semelhante ao criar um LatLngBounds
e usar um CameraUpdateFactory.newLatLngZoom(LatLng latLng, float zoom)
com LatLngBounds
.getCenter()
. O método getCenter () retorna o centro geográfico de LatLngBounds
.
Kotlin
val australiaBounds = LatLngBounds( LatLng((-44.0), 113.0), // SW bounds LatLng((-10.0), 154.0) // NE bounds ) map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.center, 10f))
Java
LatLngBounds australiaBounds = new LatLngBounds( new LatLng(-44, 113), // SW bounds new LatLng(-10, 154) // NE bounds ); map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.getCenter(), 10));
Uma sobrecarga do método, newLatLngBounds(boundary, width, height,
padding)
, permite especificar a largura e a altura de um retângulo em pixels para que correspondam às dimensões do mapa. O retângulo é posicionado de modo que seu centro seja igual ao do ponto de visão do mapa (para que, se as dimensões especificadas forem as mesmas da visualização do mapa, o retângulo coincidirá com a visualização do mapa). A CameraUpdate
retornada moverá a câmera para que o LatLngBounds
especificado fique centralizado na tela dentro do retângulo determinado, no maior nível de zoom possível, considerando-se o preenchimento necessário.
Observação: só utilize o método mais simples newLatLngBounds(boundary, padding)
para gerar um CameraUpdate
se ele for usado para mover a câmera, depois que o mapa passar pelo layout. Durante o layout, a API calcula os limites de exibição do mapa, que são necessários para projetar corretamente a caixa delimitadora. Em comparação, você pode usar a CameraUpdate
retornada pelo método newLatLngBounds(boundary, width, height, padding)
mais complexo a qualquer momento, mesmo antes de o mapa passar pelo layout, já que a API calcula os limites de exibição a partir dos argumentos que você transmite.
Restringir o deslocamento do usuário a uma determinada área
Nos cenários acima, você define os limites do mapa, mas o usuário pode rolar ou deslocar o mapa para fora desses limites. Em vez disso, pode ser útil restringir os limites centrais de lat/lng do ponto focal do mapa (o alvo da câmera) para que os usuários somente possam rolar e deslocar o mapa dentro desses limites. Por exemplo, um app de varejo de um shopping ou aeroporto pode querer restringir o mapa a determinados limites, permitindo que os usuários rolem e movimentem o mapa dentro desses limites.
Kotlin
// Create a LatLngBounds that includes the city of Adelaide in Australia. val adelaideBounds = LatLngBounds( LatLng(-35.0, 138.58), // SW bounds LatLng(-34.9, 138.61) // NE bounds ) // Constrain the camera target to the Adelaide bounds. map.setLatLngBoundsForCameraTarget(adelaideBounds)
Java
// Create a LatLngBounds that includes the city of Adelaide in Australia. LatLngBounds adelaideBounds = new LatLngBounds( new LatLng(-35.0, 138.58), // SW bounds new LatLng(-34.9, 138.61) // NE bounds ); // Constrain the camera target to the Adelaide bounds. map.setLatLngBoundsForCameraTarget(adelaideBounds);
O diagrama a seguir mostra um cenário em que o alvo da câmera está restrito a uma área ligeiramente maior que a janela de visualização. O usuário pode rolar e deslocar o mapa, desde que o alvo da câmera permaneça dentro da área limitada. A cruz representa o alvo da câmera:
O mapa sempre preenche a janela de visualização, mesmo que o resultado seja a exibição de áreas fora dos limites definidos. Por exemplo, se você posicionar o alvo da câmera no canto da área limitada, a área além do canto ficará visível na janela de visualização, mas os usuários não poderão rolar o mapa para essa área. O diagrama a seguir ilustra esse cenário. A cruz representa o alvo da câmera:
No diagrama a seguir, o alvo da câmera tem limites muito restritos, oferecendo ao usuário pouca oportunidade para rolar ou deslocar o mapa. A cruz representa o alvo da câmera:
Como atualizar a visualização da câmera
Para aplicar uma CameraUpdate
ao mapa, você pode mover a câmera instantaneamente ou animá-la com suavidade. Para mover a câmera instantaneamente com o CameraUpdate
fornecido, chame GoogleMap.moveCamera(CameraUpdate)
.
Você pode tornar a experiência do usuário mais agradável, especialmente nos movimentos curtos, animando a mudança. Para fazer isso, em vez de chamar GoogleMap.moveCamera
, chame GoogleMap.animateCamera
.
O mapa se move suavemente para os novos atributos. A forma mais detalhada desse método, GoogleMap.animateCamera(cameraUpdate, duration, callback)
, oferece três argumentos:
cameraUpdate
- A
CameraUpdate
descreve para onde mover a câmera. callback
- Um objeto que implementa
GoogleMap.CancellableCallback
. Essa interface generalizada para o processamento de tarefas define dois métodos, `onCancel()` e `onFinished()`. Para a animação, os métodos são solicitados nas seguintes circunstâncias:onFinish()
- Invocado se a animação passa para a conclusão sem interrupção.
onCancel()
-
Invocado se a animação é interrompida pela chamada a
stopAnimation()
ou pela inicialização de um novo movimento da câmera.Como alternativa, isso também pode ocorrer se você chamar
GoogleMap.stopAnimation()
.
duration
- Duração desejada da animação, em milissegundos, como um
int
.
Os seguintes snippets de código ilustram algumas das formas comuns de mover a câmera.
Kotlin
val sydney = LatLng(-33.88, 151.21) val mountainView = LatLng(37.4, -122.1) // Move the camera instantly to Sydney with a zoom of 15. map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15f)) // Zoom in, animating the camera. map.animateCamera(CameraUpdateFactory.zoomIn()) // Zoom out to zoom level 10, animating with a duration of 2 seconds. map.animateCamera(CameraUpdateFactory.zoomTo(10f), 2000, null) // Construct a CameraPosition focusing on Mountain View and animate the camera to that position. val cameraPosition = CameraPosition.Builder() .target(mountainView) // Sets the center of the map to Mountain View .zoom(17f) // Sets the zoom .bearing(90f) // Sets the orientation of the camera to east .tilt(30f) // Sets the tilt of the camera to 30 degrees .build() // Creates a CameraPosition from the builder map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
Java
LatLng sydney = new LatLng(-33.88,151.21); LatLng mountainView = new LatLng(37.4, -122.1); // Move the camera instantly to Sydney with a zoom of 15. map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15)); // Zoom in, animating the camera. map.animateCamera(CameraUpdateFactory.zoomIn()); // Zoom out to zoom level 10, animating with a duration of 2 seconds. map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null); // Construct a CameraPosition focusing on Mountain View and animate the camera to that position. CameraPosition cameraPosition = new CameraPosition.Builder() .target(mountainView ) // Sets the center of the map to Mountain View .zoom(17) // Sets the zoom .bearing(90) // Sets the orientation of the camera to east .tilt(30) // Sets the tilt of the camera to 30 degrees .build(); // Creates a CameraPosition from the builder map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));