I am using the flutter_carplay
(https://pub.dev/packages/flutter_carplay) plugin in my EV charging app. I need to display the chargers on the CarPlay screen based on the map's scrolls and movements in the CPPointOfInterestTemplate
. I need to know how to get the latitude and longitude bounds of the screen when it is scrolled or the position changes.
This is my Carplay FCPPointOfInterestTemplate.swift
//
// FCPPointOfInterestTemplate.swift
// flutter_carplay
//
// Created by Olaf Schneider on 15.02.22.
//
import CarPlay
@available(iOS 14.0, *)
class FCPPointOfInterestTemplate {
private(set) var _super: CPPointOfInterestTemplate?
private(set) var elementId: String
private var title: String
private var poi: [FCPPointOfInterest]
init(obj: [String: Any]) {
self.elementId = obj["_elementId"] as! String
self.title = obj["title"] as! String
self.poi = (obj["poi"] as! [[String: Any]]).map {
FCPPointOfInterest(obj: $0)
}
}
var get: CPPointOfInterestTemplate {
var pois: [CPPointOfInterest] = []
for p in poi {
pois.append(p.get)
}
let pointOfInterestTemplate = CPPointOfInterestTemplate.init(
title: self.title, pointsOfInterest: pois, selectedIndex: NSNotFound)
self._super = pointOfInterestTemplate
return pointOfInterestTemplate
}
}
@available(iOS 14.0, *)
extension FCPPointOfInterestTemplate: FCPRootTemplate {}
I need to know how to get the latitude and longitude bounds.
You need to assign an object that conforms to the CPPointOfInterestTemplateDelegate
protocol to the pointOfInterestDelegate
property of your CPPointOfInterestTemplate
.
The delegates pointOfInterestTemplate(_:didChangeMapRegion:)
method will be called when the map region changes.
In this method you can access the region
argument to obtain the MKCoordinateRegion
that is currently shown on the map.
The region has a center
property that gives you the latitude and longitude of the center of the map and a span
property that gives you the latitude and longitude deltas.
Since the Earth is not a perfect sphere, the top/bottom/left/right of the map won't exactly be the center plus/minus half the deltas, but it will be close enough.
The other method you may want to implement in your delegate is pointOfInterestTemplate(_:didSelectPointOfInterest:)
so that you can respond to the user selecting one of your points of interest.
For example:
extension FCPPointOfInterestTemplate: CPPointOfInterestTemplateDelegate {
func pointOfInterestTemplate(_ pointOfInterestTemplate: CPPointOfInterestTemplate, didChangeMapRegion region: MKCoordinateRegion) {
let center = region.center
let latitudeDelta2 = region.span.latitudeDelta/2
let longitudeDelta2 = region.span.longitudeDelta/2
let topLeft = CLLocationCoordinate2D(latitude: center.latitude-latitudeDelta2, longitude:center.longitude-longitudeDelta2)
let bottomRight = CLLocationCoordinate2D(latitude: center.latitude+latitudeDelta2, longitude:center.longitude+longitudeDelta2)
// Now do something with coordinates
}
func pointOfInterestTemplate(_ pointOfInterestTemplate:CPPointOfInterestTemplate, didSelectPointOfInterest pointOfInterest: CPPointOfInterest) {
// Do something with selected POI
}
}
And then in your init
you need to set the delegate:
var get: CPPointOfInterestTemplate {
var pois = pois.map { $0.get }
let pointOfInterestTemplate = CPPointOfInterestTemplate(
title: self.title, pointsOfInterest: pois, selectedIndex: NSNotFound)
self._super = pointOfInterestTemplate
pointOfInterestTemplate.pointOfInterestDelegate = self
return pointOfInterestTemplate
}
Unfortunately it seems that the Flutter CarPlay package doesn't keep a strong reference to the FCPPointOfInterestTemplate
object, so the delegate methods don't get called.
The package probably needs to be updated to handle these delegate methods and provide callbacks to the Flutter layer via a method channel.