简体   繁体   中英

Custom marker infowindow using google maps ios sdk and swiftui

In my app I am trying to make a custom infowindow appear when a marker (GMSMarker) is tapped using GoogleMaps and a SwiftUI view.

Ive been referencing Google's documentation here: https://developers.google.com/maps/documentation/ios-sdk/reference/protocol_g_m_s_map_view_delegate-p

At the moment I can display a custom infowindow using the 'markerInfoWindow' method on my GMSMapViewDelegate by returning a UIView, but since almost all of my app is built using swiftui views I would like to be able to display an existing swiftui view rather than recreate the view as a UIView.

Here is my current function that creates then displays a basic UIView as the infowindow (its a grey box with text on it):

    func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView {
        print("Showing marker infowindow")
        let mInfoWindow = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width - 48, height: 200))
        mInfoWindow.backgroundColor = UIColor.lightGray
        mInfoWindow.layer.cornerRadius = 6

        let lbl1 = UILabel(frame: CGRect.init(x: 8, y: 8, width: view.frame.size.width - 16, height: 15))
        lbl1.text = "Hi there!"
        mInfoWindow.addSubview(lbl1)


        return mInfoWindow
    }

Here is the swiftui view I would like to be able to show instead:

import SwiftUI
import UIKit

struct MarkerInfoWindow: View {
    var body: some View {

        HStack {
            Text("Image here")

            VStack {
                Text("Content 1")
                Text("Content 2")

            }

            Text("button here")
        }

    }
}

Im fairly new to swift so this may be obvious to more experienced developers, but is there any way that I can return my swiftui view as a UIView so that I can display it in the infowindow?

Or is there a way to easily style my UIView so it can be a mixture of HStacks and VStacks if thats my only option?

I think that you could use UIHostingController in this situation. I haven't tried this in Google maps as I don't have a project that uses them so YMMV, but it could at least give you a starting point.

To use UIHostingController we can pass the SwiftUI view that we want to use. You can style the size of it inside your SwiftUI or you can add a frame to the callout.

func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView {
    print("Showing marker infowindow") 
    let callout = UIHostingController(rootView: MarkerInfoWindow())
    callout.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width - 48, height: 200)
    return callout.view
}

Your MarkerInfoWindow looks like you are planning to have a button in it, I am not sure how you would implement that, it may be a simple case of adding a button in the SwiftUI code, though I know from past experience that it is difficult to interact with a callout if the button isn't inside one of the callout accessories.


This is what I did in MapKit to show the callout

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    let callout = UIHostingController(rootView: MarkerInfoWindow())
    callout.view.frame = CGRect(x: 0, y: 0, width: mapView.frame.width - 48, height: 200)
    view.addSubview(callout.view)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM