From 5888cdfcb29ffbdfbf601d886a441afc019aa914 Mon Sep 17 00:00:00 2001 From: Aleksandar Stojiljkovic Date: Mon, 12 Aug 2019 18:08:14 +0300 Subject: [PATCH] Simplify anchor point calculation and puck centering Decouple dependency content insets -> anchor point -> padding/content insets broken after https://github.com/mapbox/mapbox-gl-native/pull/14664 introduced animated interpolation for padding change. Remove the need to specify center for puck view - use the approach where content inset is keeping it centered. Take safeArea into account when calculating contentInsets. Addresses: https://github.com/mapbox/mapbox-gl-native/issues/15232, https://github.com/mapbox/mapbox-gl-native/issues/15233 Related to: https://github.com/mapbox/mapbox-navigation-ios/issues/2165, Fixes: https://github.com/mapbox/mapbox-navigation-ios/issues/2145 --- MapboxNavigation/NavigationMapView.swift | 22 +++---------------- MapboxNavigation/RouteMapViewController.swift | 19 +++++++++++++++- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 2cd234324e2..f3fe8d3777a 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -148,19 +148,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { if let anchorPoint = navigationMapViewDelegate?.navigationMapViewUserAnchorPoint?(self), anchorPoint != .zero { return anchorPoint } - - // Inset by the safe area to avoid notches. - // Inset by the content inset to avoid application-defined content. - var contentFrame = bounds.inset(by: safeArea).inset(by: contentInset) - - // Avoid letting the puck go partially off-screen, and add a comfortable padding beyond that. - let courseViewBounds = userCourseView?.bounds ?? .zero - 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)) - - // Get the bottom-center of the remaining frame. - assert(!contentFrame.isInfinite) - return CGPoint(x: contentFrame.midX, y: contentFrame.maxY) + let contentFrame = bounds.inset(by: contentInset) + return CGPoint(x: contentFrame.midX, y: contentFrame.midY) } /** @@ -194,8 +183,6 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { if let userCourseView = userCourseView { if let location = userLocationForCourseTracking { updateCourseTracking(location: location, animated: false) - } else { - userCourseView.center = userAnchorPoint } addSubview(userCourseView) } @@ -337,10 +324,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { if tracksUserCourse { let newCamera = camera ?? MGLMapCamera(lookingAtCenter: location.coordinate, altitude: altitude, pitch: 45, heading: location.course) let function: CAMediaTimingFunction? = animated ? CAMediaTimingFunction(name: .linear) : nil - let point = userAnchorPoint - let padding = UIEdgeInsets(top: point.y, left: point.x, bottom: bounds.height - point.y, right: bounds.width - point.x) - setCamera(newCamera, withDuration: duration, animationTimingFunction: function, edgePadding: padding, completionHandler: nil) - userCourseView?.center = userAnchorPoint + setCamera(newCamera, withDuration: duration, animationTimingFunction: function, completionHandler: nil) } else { // Animate course view updates in overview mode UIView.animate(withDuration: duration, delay: 0, options: [.curveLinear], animations: { [weak self] in diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index 90596b84080..cb5e6136adc 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -396,13 +396,30 @@ class RouteMapViewController: UIViewController { let instructionBannerHeight = topBannerContainerView.bounds.height let bottomBannerHeight = bottomBannerContainerView.bounds.height - var insets = UIEdgeInsets(top: instructionBannerHeight, left: 0.0, bottom: bottomBannerHeight, right: 0.0) + // Inset by the safe area to avoid notches. + var insets = mapView.safeArea + insets.top += instructionBannerHeight + insets.bottom += bottomBannerHeight if overviewing { insets += NavigationMapView.courseViewMinimumInsets let routeLineWidths = MBRouteLineWidthByZoomLevel.compactMap { $0.value.constantValue as? Int } insets += UIEdgeInsets(floatLiteral: Double(routeLineWidths.max() ?? 0)) + } else if mapView.tracksUserCourse { + // 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