Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable show/hide for location puck accuracyRadius #629

Merged
merged 10 commits into from
Sep 8, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions Apps/Examples/Examples/All Examples/Custom2DPuckExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import MapboxMaps
@objc(Custom2DPuckExample)
public class Custom2DPuckExample: UIViewController, ExampleProtocol {

internal var toggleAccuracyRadiusButton: UIButton?
macdrevx marked this conversation as resolved.
Show resolved Hide resolved
internal var mapView: MapView!
internal var shouldToggleAccuracyRadius: Bool = true
macdrevx marked this conversation as resolved.
Show resolved Hide resolved

override public func viewDidLoad() {
super.viewDidLoad()
Expand All @@ -13,15 +15,76 @@ public class Custom2DPuckExample: UIViewController, ExampleProtocol {
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(mapView)

// Setup and create button for toggling accuracy ring
self.setupToggleShowAccuracyButton()

// Granularly configure the location puck with a `Puck2DConfiguration`
let configuration = Puck2DConfiguration(topImage: UIImage(named: "star"))
mapView.location.options.puckType = .puck2D(configuration)
mapView.location.options.puckBearingSource = .course

// Center map over the user's current location
mapView.mapboxMap.onNext(.mapLoaded, handler: { [weak self] _ in
guard let self = self else { return }

if let currentLocation = self.mapView.location.latestLocation {
let cameraOptions = CameraOptions(center: currentLocation.coordinate, zoom: 18.0)
self.mapView.camera.ease(to: cameraOptions, duration: 2.0)
}
})

// Setup a toggle button to show how to toggle the accuracy radius
mapView.mapboxMap.onEvery(.cameraChanged, handler: { [weak self] _ in
guard let self = self,
let button = self.toggleAccuracyRadiusButton else {
macdrevx marked this conversation as resolved.
Show resolved Hide resolved
return
}

if self.mapView.cameraState.zoom >= 18.0 {
button.isHidden = false

} else {
button.isHidden = true
}
macdrevx marked this conversation as resolved.
Show resolved Hide resolved
})
}

override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// The below line is used for internal testing purposes only.
finish()
}

@objc func showHideAccuracyRadius() {
var configuration = Puck2DConfiguration(topImage: UIImage(named: "star"))
if shouldToggleAccuracyRadius {
configuration.showsAccuracyRing = true
shouldToggleAccuracyRadius = false
self.toggleAccuracyRadiusButton!.setTitle("Disable Accuracy Radius", for: .normal)
} else {
configuration.showsAccuracyRing = false
shouldToggleAccuracyRadius = true
self.toggleAccuracyRadiusButton!.setTitle("Enable Accuracy Radius", for: .normal)
}
macdrevx marked this conversation as resolved.
Show resolved Hide resolved

mapView.location.options.puckType = .puck2D(configuration)
}

private func setupToggleShowAccuracyButton() {
// Button setup
let button = UIButton(frame: CGRect.zero)
button.backgroundColor = .systemBlue
button.addTarget(self, action: #selector(self.showHideAccuracyRadius), for: .touchUpInside)
button.setTitle("Enable Accuracy Radius", for: .normal)
button.setTitleColor(.white, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(button)

// Constraints
button.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 20.0).isActive = true
button.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -20.0).isActive = true
button.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 650.0).isActive = true

self.toggleAccuracyRadiusButton = button
}
}
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ Mapbox welcomes participation and contributions from everyone.
* Enable instant transitions for data driven paint layer properties ([#628](https://github.com/mapbox/mapbox-maps-ios/pull/628))
* Offload networking tasks at the init phase ([#631](https://github.com/mapbox/mapbox-maps-ios/pull/631))
* 3D pucks will now be rendered over other 3D content and occluded by terrain ([#641](https://github.com/mapbox/mapbox-maps-ios/pull/641))
<<<<<<< HEAD
macdrevx marked this conversation as resolved.
Show resolved Hide resolved
* Added a public, failable, component-wise initializer to `StyleColor` ([#650](https://github.com/mapbox/mapbox-maps-ios/pull/650))
* Updated `StyleColor`'s `Decodable` support to be able to handle rgba color strings as well as rgba expressions ([#650](https://github.com/mapbox/mapbox-maps-ios/pull/650))
* Made generated enums conform to `CaseIterable` ([#650](https://github.com/mapbox/mapbox-maps-ios/pull/650))
* Offload networking tasks at the init phase ([#](https://github.com/mapbox/mapbox-maps-ios/pull/))
* Location puck can now hide the accuracy ring. The default value is to hide the accuracy ring. In order to enable the ring, set the `showAccuracyRing` property in `Puck2DConfiguration` to `true`. [#629](https://github.com/mapbox/mapbox-maps-ios/pull/629)

### Bug fixes 🐞

Expand Down
17 changes: 13 additions & 4 deletions Sources/MapboxMaps/Location/Pucks/Puck2D.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,19 @@ public struct Puck2DConfiguration: Equatable {
/// The size of the images, as a scale factor applied to the size of the specified image.
public var scale: Value<Double>?

/// Flag determining if the horizontal accuracy ring should be shown arround the Puck. default value is false
public var showsAccuracyRing: Bool

public init(topImage: UIImage? = nil,
bearingImage: UIImage? = nil,
shadowImage: UIImage? = nil,
scale: Value<Double>? = nil) {
scale: Value<Double>? = nil,
showsAccuracyRing: Bool = false) {
self.topImage = topImage
self.bearingImage = bearingImage
self.shadowImage = shadowImage
self.scale = scale
self.showsAccuracyRing = showsAccuracyRing
}

internal var resolvedTopImage: UIImage? {
Expand Down Expand Up @@ -181,11 +186,15 @@ internal extension Puck2D {
layer.topImageSize = configuration.resolvedScale
layer.bearingImageSize = configuration.resolvedScale
layer.shadowImageSize = configuration.resolvedScale
layer.accuracyRadius = .constant(location.horizontalAccuracy)
layer.emphasisCircleRadiusTransition = StyleTransition(duration: 0, delay: 0)
layer.bearingTransition = StyleTransition(duration: 0, delay: 0)
layer.accuracyRadiusColor = .constant(StyleColor(UIColor(red: 0.537, green: 0.812, blue: 0.941, alpha: 0.3)))
layer.accuracyRadiusBorderColor = .constant(StyleColor(.lightGray))

// Horizontal accuracy ring is an optional visual for the 2D Puck
if configuration.showsAccuracyRing {
layer.accuracyRadius = .constant(location.horizontalAccuracy)
layer.accuracyRadiusColor = .constant(StyleColor(UIColor(red: 0.537, green: 0.812, blue: 0.941, alpha: 0.3)))
layer.accuracyRadiusBorderColor = .constant(StyleColor(.lightGray))
}
macdrevx marked this conversation as resolved.
Show resolved Hide resolved

// Add layer to style
try style._addPersistentLayer(layer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,60 @@ class Puck2DIntegrationTests: MapViewIntegrationTestCase {
wait(for: [addedPrecisePuckExpectation, removedPrecisePuckExpectation, addedApproximatePuckExpectation], timeout: 5)
}

func testAccuracyRadiusIsHidden() throws {
let style = try XCTUnwrap(self.style)
style.uri = .streets

let location = Location(with: CLLocation(latitude: 1, longitude: 1))
let accuracyRingIsHiddenExpectation = XCTestExpectation(description: "Layer does not contain an accuracy ring")

didFinishLoadingStyle = { _ in
let puck = Puck2D(puckStyle: .precise,
puckBearingSource: .heading,
locationSupportableMapView: self.mapView!,
style: style,
configuration: Puck2DConfiguration())
do {
try puck.createPreciseLocationIndicatorLayer(location: location)
} catch {
XCTFail("Failed to create a precise location indicator layer.")
}

let layer = try! style.layer(withId: "puck") as LocationIndicatorLayer
if layer.accuracyRadius == nil {
accuracyRingIsHiddenExpectation.fulfill()
}
}
wait(for: [accuracyRingIsHiddenExpectation], timeout: 5)
macdrevx marked this conversation as resolved.
Show resolved Hide resolved
}

func testAccuracyRadiusIsShown() throws {
let style = try XCTUnwrap(self.style)
style.uri = .streets

let location = Location(with: CLLocation(latitude: 1, longitude: 1))
let accuracyRingIsVisibleExpectation = XCTestExpectation(description: "Layer contains an accuracy ring")

didFinishLoadingStyle = { _ in
let puck = Puck2D(puckStyle: .precise,
puckBearingSource: .heading,
locationSupportableMapView: self.mapView!,
style: style,
configuration: Puck2DConfiguration(showsAccuracyRing: true))
do {
try puck.createPreciseLocationIndicatorLayer(location: location)
} catch {
XCTFail("Failed to create a precise location indicator layer.")
}

let layer = try! style.layer(withId: "puck") as LocationIndicatorLayer
if layer.accuracyRadius != nil {
accuracyRingIsVisibleExpectation.fulfill()
}
}
wait(for: [accuracyRingIsVisibleExpectation], timeout: 5)
macdrevx marked this conversation as resolved.
Show resolved Hide resolved
}

func testLayerPersistence() throws {
let style = try XCTUnwrap(self.style)

Expand Down