12 Ago, 2013 12:38

Utilizando o Google Maps no seu Aplicativo iOS - Parte 2

InfoWindow padrão

A InfoWindow padrão é muito simples de usar. Basta você definir as propriedades title e snippet do GMSMarker, ex:

GMSMarker *mobits = [GMSMarker markerWithPosition:CLLocationCoordinate2DMake(-22.90644,-43.177171)];

mobits.title = @"Mobits";
mobits.snippet = @"Ideias para um mundo móvel";

mobits.map = self.mapView;
mobits.icon = [GMSMarker markerImageWithColor:[UIColor clearColor]];

Quando o usuário tocar no marcador definido acima, o próprio SDK fará todo o tratamento necessário para mostrar uma InfoWindow como abaixo.

InfoWindow padrão do SDK do Google Maps para iOS

Alterando a aparência da InfoWindow padrão

Se o visual acima não atende às suas expectativas, é possível substituir a UIView utilizada pelo SDK por uma criada por você.

O primeiro passo é definir o seu controller como delegate do seu mapa:

self.mapView.delegate = self;

Em seguida, crie uma UIView ou subclasse no seu XIB ou programaticamente e implemente o método de GMSMapViewDelegate de maneira semelhante a abaixo.

- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker {
    self.tituloLabel.text = marker.title;
    self.subtituloLabel.text = marker.snippet;

    return self.myInfoWindowView;
}

O resultado será parecido com este:

Criando sua própria InfoWindow

OBS: Como você pode ver, a UIView acima não recebe as sombras nem a seta para baixo presentes na InfoWindow padrão. É sua responsabilidade preparar os elementos visuais que você quiser que apareçam.

Interagindo com a InfoWindow

O SDK permite detectar quando o usuário tocar na InfoWindow para poder executar ações em resposta. Para isso, basta implementar o método de GMSMapViewDelegate abaixo:

- (void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker {
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"InfoWindow" message:@"Tocou na InfoWindow" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

    [alertView show];
}

Desta maneira simples, teremos o resultado:

Detectando o toque na InfoWindow

A solução acima funciona tanto com a InfoWindow padrão quanto com a personalizada.

Substituindo completamente a InfoWindow

Apesar de você poder detectar o toque na InfoWindow, não é possível realizar outras interações com ela, como, p. ex., colocar botões dentro da InfoWindow para o usuário realizar diversas ações. O motivo é que o SDK renderiza da UIView em uma imagem que não permite interações ou animações.

Se você precisa de recursos mais avançados, terá que implementar sua própria InfoWindow e tratar a exibição, posicionamento e interações por sua conta. Observe o código abaixo:

- (void)viewDidLoad {
    ...
    self.myInfoWindowView.hidden = YES;
    [self.mapView addSubview:self.myInfoWindowView];  // A
    ...
}

#pragma mark - GMSMapViewDelegate

- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
    self.myInfoWindowView.hidden = NO; // B

    self.tituloLabel.text = marker.title;
    self.subtituloLabel.text = marker.snippet;

    GMSCameraPosition *camera = [GMSCameraPosition cameraWithTarget:marker.position
                                                               zoom:10];
    [mapView setCamera:camera]; // C

    markerSelecionado = marker;

    [self posicionaInfoWindowView]; // D

    return YES; //E
}

- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
    self.myInfoWindowView.hidden = YES; // F
    markerSelecionado = nil;
}

- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position {
    if (!self.myInfoWindowView.hidden) {
        [self posicionaInfoWindowView]; // G
    }
}

#pragma mark - Private

- (void)posicionaInfoWindowView {

    CGPoint pontoNaMapView = [self.mapView.projection pointForCoordinate:markerSelecionado.position];
    CGRect infoFrame = self.myInfoWindowView.frame;

    infoFrame.origin.x = round(pontoNaMapView.x - CGRectGetWidth(infoFrame)/2);
    infoFrame.origin.y = round(pontoNaMapView.y - markerSelecionado.icon.size.height - CGRectGetHeight(infoFrame));

    self.myInfoWindowView.frame = infoFrame; // H
}

O primeiro passo é adicionar sua UIView como uma subview escondida do mapa (A).

Quando o usuário tocar no marcador, você deve exibir a UIView (B), posicionar a câmera sobre o marcado (C), calcular a posição da UIView sobre o marcador (D e H) e avisar ao mapa que ele não deve executar o procedimento padrão de toque (E).

Se o usuário tocar em outra área do mapa fora do marcador e da UIView, você deve esconder a UIView (F).

Se o usuário arrastar, der zoom ou executar qualquer outra ação que modifique a câmera, você deve reposicionar a UIView de acordo (G).

Executando os passos acima, você pode criar sua própria InfoWindow com botões e animações que quiser como no exemplo abaixo.

InfoWindow com botões

Selecionado o botão na InfoWindow

Até a próxima, com recursos mais avançados do SDK.

Ao navegar neste site, você consente o uso de cookies nossos e de terceiros, que coletam informações anônimas e são essenciais para melhorar sua experiência em nosso site.