Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
OrganizationEventAdvent CalendarQiitadon (β)
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.


Android Custom Info Window for GoogleMaps Marker responsive to touch events

When the user clicks on a marker, an info window is expected. Here, we demonstrate how to add a custom info window (a subclass of UIView) which responds to user touch events.

First, we must create the CustomCalloutView, a container which can hold any content. Regardless of the contents, we must add a tap gesture recognizer so that this callout can respond to touch events.

class CustomInfoWindowView: UIView {
    convenience init() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(onTap))
        tap.numberOfTapsRequired = 1

    @objc func onTap() {}

We must also create a structure that links a marker with its associated custom info window.
When a custom info window is showing, we should maintain a reference to this structure so that future updates to its position can be performed.

struct SelectedInfoWindow {

    var marker: GMSMarker? = nil
    var infoWindow: UIView? = nil

    init(infoWindow: UIView, marker: GMSMarker) {
        self.infoWindow = infoWindow
        self.marker = marker

When the user taps a marker, we add the CustomCalloutView as a subview of the mapView, making sure to generate the reference structure above after removing past info windows.

We also immediately set the position of the info window by calling self.updateInfoWindowPosition() as described below. This function must return "true" to ensure that the default info window does not appear.

func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {

    self.mapView?.subviews.filter{ $0 is CustomInfoWindowView }.forEach{

    let infoWindow = CustomInfoWindowView()
    self.selectedInfoWindow = SelectedInfoWindow(infoWindow: infoWindow, marker: marker)

    return true

Here, an info window is removed and the reference structure deleted.

func removeInfoWindow() {
        let window = self.selectedInfoWindow?.infoWindow,
        let marker = self.selectedInfoWindow?.marker
        else {

    self.selectedInfoWindow = nil

The central position of the info window is set relative to the center point of its associated marker, using mapView?.projection.point(for:). It is recommended to offset these centers so that the marker is not covered by the info window; this offset is therefore calculated from the size of the marker icon and custom infoWindow.

We should also call this function if the CustomCalloutView layout changes (i.e. override layoutSubViews to catch this event), because the infoWindow offset may have changed.

public func updateInfoWindowPosition() {

        let infoWindow = self.selectedInfoWindow?.infoWindow,
        let marker = self.selectedInfoWindow?.marker,
        let center = self.mapView?.projection.point(for: marker.position)
        else { return }

    window.center = center

    let markerHeight = marker.icon?.size.height ?? 0.0
    let infoWindowHeight = infoWindow.frame.height
    var offset: CGFloat = -0.5 * infoWindowHeight - markerHeight

    infoWindow.frame = window.frame.offsetBy(dx: 0.0, dy: offset)

When the map position changes, we must continue to update the infoWindow position.

func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {

Finally, when the user deselects the marker by pressing the map at a location other than a marker, we must call the method to remove the info window.

func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Help us understand the problem. What are the problem?