Skip to content

Commit

Permalink
Work around mapbox-gl-native/15574. Avoid re-setting content inset to…
Browse files Browse the repository at this point in the history
… safeArea. Panning fix.

Fix CarPlay puck positioning, panning away from navigation, navigation -> overview transitions.

The workaround should be future proof as the mapbox/mapbox-gl-native#15574 exists only with MGLMapView.contentInset.
Additionally, it simplifies the code as it doesn't need to ensure that safeArea and contentInset are kept in sync: according to work in #2211, contentInset is to be used to position puck and this causes map position sudden change when panning.

Fixes: #2190
  • Loading branch information
astojilj authored and 1ec5 committed Oct 2, 2019
1 parent c4ac726 commit 2e540c0
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 36 deletions.
15 changes: 2 additions & 13 deletions MapboxNavigation/CarPlayManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -620,17 +620,6 @@ extension CarPlayManager: CPMapTemplateDelegate {
}

public func mapTemplate(_ mapTemplate: CPMapTemplate, didUpdatePanGestureWithTranslation translation: CGPoint, velocity: CGPoint) {
let mapView: NavigationMapView
if let navigationViewController = currentNavigator, mapTemplate == navigationViewController.mapTemplate {
mapView = navigationViewController.mapView!
} else if let carPlayMapViewController = carPlayMapViewController {
mapView = carPlayMapViewController.mapView
} else {
return
}

// Make sure the content inset is always up to date in case the safe area changes during a gesture.
mapView.setContentInset(mapView.safeArea, animated: false, completionHandler: nil)
updatePan(by: translation, mapTemplate: mapTemplate, animated: false)
}

Expand All @@ -649,7 +638,7 @@ extension CarPlayManager: CPMapTemplateDelegate {
}

func coordinate(of offset: CGPoint, in mapView: NavigationMapView) -> CLLocationCoordinate2D {
let contentFrame = mapView.bounds.inset(by: mapView.safeArea)
let contentFrame = mapView.bounds.inset(by: mapView.contentInset)
let centerPoint = CGPoint(x: contentFrame.midX, y: contentFrame.midY)
let endCameraPoint = CGPoint(x: centerPoint.x - offset.x, y: centerPoint.y - offset.y)

Expand All @@ -663,7 +652,7 @@ extension CarPlayManager: CPMapTemplateDelegate {

// Determine the screen distance to pan by based on the distance from the visual center to the closest side.
let mapView = carPlayMapViewController.mapView
let contentFrame = mapView.bounds.inset(by: mapView.safeArea)
let contentFrame = mapView.bounds.inset(by: mapView.contentInset)
let increment = min(mapView.bounds.width, mapView.bounds.height) / 2.0

// Calculate the distance in physical units from the visual center to where it would be after panning downwards.
Expand Down
20 changes: 7 additions & 13 deletions MapboxNavigation/CarPlayMapViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ public class CarPlayMapViewController: UIViewController {
return coarseLocationManager
}()

var isOverviewingRoutes: Bool = false
var isOverviewingRoutes: Bool = false {
didSet {
// Workaround for https://github.com/mapbox/mapbox-gl-native/issues/15574
// In overview mode, content insets are set to .zero, avoid getting them changed.
automaticallyAdjustsScrollViewInsets = !isOverviewingRoutes
}
}

var mapView: NavigationMapView {
get {
Expand Down Expand Up @@ -194,18 +200,6 @@ public class CarPlayMapViewController: UIViewController {

override public func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()

var edgePadding = view.safeArea
edgePadding += NavigationMapView.defaultPadding

if let userCourseView = mapView.userCourseView {
let midX = userCourseView.bounds.midX
let midY = userCourseView.bounds.midY
edgePadding += UIEdgeInsets(top: midY, left: midX, bottom: midY, right: midX)
}

mapView.setContentInset(edgePadding, animated: false, completionHandler: nil)

guard let active = mapView.routes?.first else {
mapView.setUserTrackingMode(.followWithCourse, animated: true, completionHandler: nil)
return
Expand Down
48 changes: 41 additions & 7 deletions MapboxNavigation/CarPlayNavigationViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,34 @@ public class CarPlayNavigationViewController: UIViewController, NavigationMapVie
guard let mapView = mapView else { return }

mapView.enableFrameByFrameCourseViewTracking(for: 1)

mapView.setContentInset(view.safeArea, animated: true) { [weak self] in
guard let self = self, self.tracksUserCourse else { return }
mapView.fit(to: self.navigationService.route, facing: 0, animated: true)
}

public override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if (isOverviewingRoutes) { return } // Don't move content when overlays change.
guard let mapView = mapView else { return }
mapView.contentInset = contentInset(forOverviewing: false)
}

func contentInset(forOverviewing overviewing: Bool) -> UIEdgeInsets {
guard let mapView = mapView else { return .zero }
var insets = mapView.safeArea
if !overviewing {
// Puck position calculation - position it just above the bottom of the content area.
var contentFrame = mapView.bounds.inset(by: insets)

// Avoid letting the puck go partially off-screen, and add a comfortable padding beyond that.
let courseViewBounds = mapView.userCourseView?.bounds ?? .zero
// If it is not possible to position it right above the content area, center it at the remaining space.
contentFrame = contentFrame.insetBy(dx: min(NavigationMapView.courseViewMinimumInsets.left + courseViewBounds.width / 2.0, contentFrame.width / 2.0),
dy: min(NavigationMapView.courseViewMinimumInsets.top + courseViewBounds.height / 2.0, contentFrame.height / 2.0))
assert(!contentFrame.isInfinite)

let y = contentFrame.maxY
let height = mapView.bounds.height
insets.top = height - insets.bottom - 2 * (height - insets.bottom - y)
}
return insets;
}

/**
Expand Down Expand Up @@ -233,27 +256,38 @@ public class CarPlayNavigationViewController: UIViewController, NavigationMapVie
set {
let progress = navigationService.routeProgress
if !tracksUserCourse && newValue {

isOverviewingRoutes = false;
mapView?.recenterMap()
mapView?.addArrow(route: progress.route,
legIndex: progress.legIndex,
stepIndex: progress.currentLegProgress.stepIndex + 1)
mapView?.setContentInset(contentInset(forOverviewing: false), animated: true, completionHandler: nil)
} else if tracksUserCourse && !newValue {

isOverviewingRoutes = !isPanningAway;
guard let userLocation = self.navigationService.router.location?.coordinate,
let coordinates = navigationService.route.coordinates else {
return
}
mapView?.enableFrameByFrameCourseViewTracking(for: 1)
mapView?.setOverheadCameraView(from: userLocation, along: coordinates, for: .zero)
mapView?.contentInset = contentInset(forOverviewing: isOverviewingRoutes)
if (isOverviewingRoutes) {
mapView?.setOverheadCameraView(from: userLocation, along: coordinates, for: contentInset(forOverviewing: true))
}
}
}
}

// Tracks if tracksUserCourse was set to false from overview button
// or panned away.
var isPanningAway = false;
var isOverviewingRoutes = false;

public func beginPanGesture() {
isPanningAway = true;
tracksUserCourse = false
mapView?.tracksUserCourse = false
mapView?.enableFrameByFrameCourseViewTracking(for: 1)
isPanningAway = false;
}

@objc func visualInstructionDidChange(_ notification: NSNotification) {
Expand Down
10 changes: 8 additions & 2 deletions MapboxNavigation/NavigationMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,11 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate {

setUserTrackingMode(.none, animated: false, completionHandler: nil)
let line = MGLPolyline(coordinates: coords, count: UInt(coords.count))
let camera = cameraThatFitsShape(line, direction: direction, edgePadding: .zero)

// Workaround for https://github.com/mapbox/mapbox-gl-native/issues/15574
// Set content insets .zero, before cameraThatFitsShape + setCamera.
contentInset = .zero
let camera = cameraThatFitsShape(line, direction: direction, edgePadding: safeArea + NavigationMapView.defaultPadding)
setCamera(camera, animated: animated)
}

Expand Down Expand Up @@ -1085,7 +1088,10 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate {
let currentCamera = self.camera
currentCamera.pitch = 0
currentCamera.heading = 0


// Workaround for https://github.com/mapbox/mapbox-gl-native/issues/15574
// Set content insets .zero, before cameraThatFitsShape + setCamera.
contentInset = .zero
let newCamera = camera(currentCamera, fitting: line, edgePadding: padding)

setCamera(newCamera, withDuration: 1, animationTimingFunction: nil) { [weak self] in
Expand Down
2 changes: 1 addition & 1 deletion MapboxNavigation/RouteMapViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ class RouteMapViewController: UIViewController {
if let coordinates = router.route.coordinates,
let userLocation = router.location?.coordinate {
mapView.contentInset = contentInset(forOverviewing: true)
mapView.setOverheadCameraView(from: userLocation, along: coordinates, for: .zero)
mapView.setOverheadCameraView(from: userLocation, along: coordinates, for: contentInset(forOverviewing: true))
}
isInOverviewMode = true
}
Expand Down

0 comments on commit 2e540c0

Please sign in to comment.