[ios] Add delegate method to specify the user location annotation’s position

Update method name

More API drafting

Add deprecation flag

Add Swift delegate integration test

Update method name and documentation

Update deprecation notices

Update method name

Offset anchor point relative to contentFrame

Update docs

Only run through switch statement if delegate is unimplemented

Account for content inset + refactor logic

Adjust edgePaddingForFollowing

Fix Swift delegate integration test

Set up integration test

Set up test location manager

.

Remove unused file reference from test

Return CGPoint value from delegate method within integration test setup

Test anchor points

Make updateUserLocationAnnotationView public

Refactor test

Update test location manager

Changelog entry

Doc fixes
This commit is contained in:
Nadia Barbosa
2018-09-17 15:45:22 -07:00
committed by Nadia Barbosa
parent 41dd886ce5
commit 7b243392e3
12 changed files with 147 additions and 8 deletions

View File

@@ -11,6 +11,12 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Fixed a crash when a style layer `*-pattern` property evaluates to nil for a particular feature. ([#12896](https://github.com/mapbox/mapbox-gl-native/pull/12896))
* Fixed an issue with view annotations (including the user location annotation) and the GL map lagging relative to each other. ([#12895](https://github.com/mapbox/mapbox-gl-native/pull/12895))
### User location
* Added `-[MGLMapViewDelegate mapViewUserLocationAnchorPoint:]` to customize the position of the user location annotation.. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907))
* Marked `-[MGLMapView setUserLocationVerticalAlignment:]` as deprecated. Use `-[MGLMapViewDelegate mapViewUserLocationAnchorPoint:]` instead. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907))
* Added the `-[MGLMapView updateUserLocationAnnotationView]` and `-[MGLMapView updateUserLocationAnnotationView:animated:]` methods to update the position of the user location annotation between location updates. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907))
* Fixed an issue where the user location annotation was positioned incorrectly when the map view had a left or right content inset. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907)) inset
### Offline maps
* Added `-[MGLOfflineStorage addContentsOfFile:withCompletionHandler:]` and `-[MGLOfflineStorage addContentsOfURL:withCompletionHandler:]` methods to add pregenerated offline packs to offline storage. ([#12791](https://github.com/mapbox/mapbox-gl-native/pull/12791))

View File

@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Used to run user location tests</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>

View File

@@ -1,6 +1,7 @@
#import "MGLMapViewIntegrationTest.h"
#import "MGLTestUtility.h"
#import "MGLMapAccessibilityElement.h"
#import "MGLTestLocationManager.h"
@interface MGLMapView (Tests)
- (MGLAnnotationTag)annotationTagAtPoint:(CGPoint)point persistingResults:(BOOL)persist;
@@ -91,6 +92,31 @@
}
}
- (void)testUserLocationWithOffsetAnchorPoint {
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(37.787357, -122.39899)];
MGLTestLocationManager *locationManager = [[MGLTestLocationManager alloc] init];
self.mapView.locationManager = locationManager;
[self.mapView setUserTrackingMode:MGLUserTrackingModeFollow animated:NO];
CGRect originalFrame = [self.mapView viewForAnnotation:self.mapView.userLocation].frame;
// Temporarily disable location tracking so we can save the value of
// the originalFrame in memory
[self.mapView setUserTrackingMode:MGLUserTrackingModeNone animated:NO];
CGPoint offset = CGPointMake(20, 20);
self.mapViewUserLocationAnchorPoint = ^CGPoint (MGLMapView *mapView) {
return offset;;
};
[self.mapView setUserTrackingMode:MGLUserTrackingModeFollow animated:NO];
CGRect offsetFrame = [self.mapView viewForAnnotation:self.mapView.userLocation].frame;
XCTAssertEqual(originalFrame.origin.x + offset.x, offsetFrame.origin.x);
XCTAssertEqual(originalFrame.origin.y + offset.y, offsetFrame.origin.y);
}
- (void)waitForCollisionDetectionToRun {
XCTAssertNil(self.renderFinishedExpectation, @"Incorrect test setup");

View File

@@ -26,6 +26,7 @@
@property (nonatomic) void (^regionWillChange)(MGLMapView *mapView, BOOL animated);
@property (nonatomic) void (^regionIsChanging)(MGLMapView *mapView);
@property (nonatomic) void (^regionDidChange)(MGLMapView *mapView, MGLCameraChangeReason reason, BOOL animated);
@property (nonatomic) CGPoint (^mapViewUserLocationAnchorPoint)(MGLMapView *mapView);
// Utility methods
- (NSString*)validAccessToken;

View File

@@ -101,6 +101,13 @@
}
}
- (CGPoint)mapViewUserLocationAnchorPoint:(MGLMapView *)mapView {
if (self.mapViewUserLocationAnchorPoint) {
return self.mapViewUserLocationAnchorPoint(mapView);
}
return CGPointZero;
}
#pragma mark - Utilities
- (void)waitForMapViewToFinishLoadingStyleWithTimeout:(NSTimeInterval)timeout {

View File

@@ -0,0 +1,10 @@
#import <XCTest/XCTest.h>
#import <Mapbox/Mapbox.h>
#import "MGLTestUtility.h"
@interface MGLTestLocationManager : NSObject<MGLLocationManager>
@end
@interface MGLTestLocationManager()
@end

View File

@@ -0,0 +1,44 @@
#import "MGLTestLocationManager.h"
// Used to supply integration tests with a simulated location manager.
// Methods that are empty are not used within integration tests and are
// therefore unimplemented.
@implementation MGLTestLocationManager
@synthesize delegate;
- (CLAuthorizationStatus)authorizationStatus { return kCLAuthorizationStatusAuthorizedAlways; }
- (void)setHeadingOrientation:(CLDeviceOrientation)headingOrientation { }
- (CLDeviceOrientation)headingOrientation { return 90; }
- (void)requestAlwaysAuthorization { }
- (void)requestWhenInUseAuthorization { }
- (void)startUpdatingHeading { }
// Simulate one location update
- (void)startUpdatingLocation
{
if ([self.delegate respondsToSelector:@selector(locationManager:didUpdateLocations:)]) {
CLLocation *location = [[CLLocation alloc] initWithLatitude:37.787357 longitude:-122.39899];
[self.delegate locationManager:self didUpdateLocations:@[location]];
}
}
- (void)stopUpdatingHeading { }
- (void)stopUpdatingLocation { }
- (void)dismissHeadingCalibrationDisplay { }
- (void)dealloc { self.delegate = nil; }
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { }
- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager { return NO; }
@end

View File

@@ -14,6 +14,8 @@
071BBB071EE77631001FB02A /* MGLImageSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */; };
076171C32139C70900668A35 /* MGLMapViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 076171C22139C70900668A35 /* MGLMapViewTests.m */; };
076171C72141A91700668A35 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 076171C62141A91700668A35 /* Settings.bundle */; };
077061D6215D97EF000FEF62 /* simple_route.json in Resources */ = {isa = PBXBuildFile; fileRef = 1F26B6C220E1A351007BCC21 /* simple_route.json */; };
077061DA215DA00E000FEF62 /* MGLTestLocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 077061D9215DA00E000FEF62 /* MGLTestLocationManager.m */; };
0778DD431F67556700A73B34 /* MGLComputedShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 0778DD401F67555F00A73B34 /* MGLComputedShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
0778DD441F67556C00A73B34 /* MGLComputedShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0778DD411F67555F00A73B34 /* MGLComputedShapeSource.mm */; };
07D8C6FB1F67560100381808 /* MGLComputedShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0778DD411F67555F00A73B34 /* MGLComputedShapeSource.mm */; };
@@ -747,6 +749,8 @@
071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLImageSourceTests.m; path = ../../darwin/test/MGLImageSourceTests.m; sourceTree = "<group>"; };
076171C22139C70900668A35 /* MGLMapViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLMapViewTests.m; path = ../../darwin/test/MGLMapViewTests.m; sourceTree = "<group>"; };
076171C62141A91700668A35 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Settings.bundle; path = app/Settings.bundle; sourceTree = SOURCE_ROOT; };
077061D9215DA00E000FEF62 /* MGLTestLocationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLTestLocationManager.m; sourceTree = "<group>"; };
077061DB215DA11F000FEF62 /* MGLTestLocationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTestLocationManager.h; sourceTree = "<group>"; };
0778DD401F67555F00A73B34 /* MGLComputedShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLComputedShapeSource.h; sourceTree = "<group>"; };
0778DD411F67555F00A73B34 /* MGLComputedShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLComputedShapeSource.mm; sourceTree = "<group>"; };
07D8C6FD1F67562800381808 /* MGLComputedShapeSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLComputedShapeSourceTests.m; path = ../../darwin/test/MGLComputedShapeSourceTests.m; sourceTree = "<group>"; };
@@ -1376,6 +1380,8 @@
CA0C27932076CA19001CE5B7 /* MGLMapViewIntegrationTest.m */,
CA0C27952076CA50001CE5B7 /* MGLMapViewIntegrationTest.h */,
CA4EB8C620863487006AB465 /* MGLStyleLayerIntegrationTests.m */,
077061DB215DA11F000FEF62 /* MGLTestLocationManager.h */,
077061D9215DA00E000FEF62 /* MGLTestLocationManager.m */,
);
path = "Integration Tests";
sourceTree = "<group>";
@@ -2825,6 +2831,7 @@
CA0C27942076CA19001CE5B7 /* MGLMapViewIntegrationTest.m in Sources */,
CAE7AD5520F46EF5003B6782 /* MGLMapSnapshotterSwiftTests.swift in Sources */,
CA0C27922076C804001CE5B7 /* MGLShapeSourceTests.m in Sources */,
077061DA215DA00E000FEF62 /* MGLTestLocationManager.m in Sources */,
CA6914B520E67F50002DB0EE /* MGLAnnotationViewIntegrationTests.m in Sources */,
CA1B4A512099FB2200EDD491 /* MGLMapSnapshotterTest.m in Sources */,
);

View File

@@ -416,7 +416,7 @@ MGL_EXPORT IB_DESIGNABLE
transition. If you don’t want to animate the change, use the
`-setUserLocationVerticalAlignment:animated:` method instead.
*/
@property (nonatomic, assign) MGLAnnotationVerticalAlignment userLocationVerticalAlignment;
@property (nonatomic, assign) MGLAnnotationVerticalAlignment userLocationVerticalAlignment __attribute__((deprecated("Use -[MGLMapViewDelegate mapViewUserLocationAnchorPoint:] instead.")));
/**
Sets the vertical alignment of the user location annotation within the
@@ -427,7 +427,20 @@ MGL_EXPORT IB_DESIGNABLE
position within the map view. If `NO`, the user location annotation
instantaneously moves to its new position.
*/
- (void)setUserLocationVerticalAlignment:(MGLAnnotationVerticalAlignment)alignment animated:(BOOL)animated;
- (void)setUserLocationVerticalAlignment:(MGLAnnotationVerticalAlignment)alignment animated:(BOOL)animated __attribute__((deprecated("Use -[MGLMapViewDelegate mapViewUserLocationAnchorPoint:] instead.")));
/**
Updates the position of the user location annotation view by retreiving the user's last
known location.
*/
- (void)updateUserLocationAnnotationView;
/**
Updates the position of the user location annotation view by retreiving the user's last
known location with a specified duration.
@param duration The duration to animate the change in seconds.
*/
- (void)updateUserLocationAnnotationViewAnimatedWithDuration:(NSTimeInterval)duration;
/**
A Boolean value indicating whether the user location annotation may display a

View File

@@ -5280,9 +5280,9 @@ public:
correctPoint.x - CGRectGetMidX(bounds),
correctPoint.y - CGRectGetMidY(bounds));
return UIEdgeInsetsMake(CGRectGetMinY(boundsAroundCorrectPoint) - CGRectGetMinY(bounds),
self.contentInset.left,
CGRectGetMaxX(boundsAroundCorrectPoint) - CGRectGetMaxX(bounds),
CGRectGetMaxY(bounds) - CGRectGetMaxY(boundsAroundCorrectPoint),
self.contentInset.right);
CGRectGetMaxX(bounds) - CGRectGetMaxX(boundsAroundCorrectPoint));
}
/// Returns the edge padding to apply during bifocal course tracking.
@@ -5998,15 +5998,21 @@ public:
/// the overall map view (but respecting the content inset).
- (CGPoint)userLocationAnnotationViewCenter
{
if ([self.delegate respondsToSelector:@selector(mapViewUserLocationAnchorPoint:)])
{
CGPoint anchorPoint = [self.delegate mapViewUserLocationAnchorPoint:self];
return CGPointMake(anchorPoint.x + self.contentInset.left, anchorPoint.y + self.contentInset.top);
}
CGRect contentFrame = UIEdgeInsetsInsetRect(self.contentFrame, self.edgePaddingForFollowingWithCourse);
if (CGRectIsEmpty(contentFrame))
{
contentFrame = self.contentFrame;
}
CGPoint center = CGPointMake(CGRectGetMidX(contentFrame), CGRectGetMidY(contentFrame));
// When tracking course, it’s more important to see the road ahead, so
// weight the user dot down towards the bottom.
switch (self.userLocationVerticalAlignment) {
case MGLAnnotationVerticalAlignmentCenter:
break;
@@ -6017,7 +6023,7 @@ public:
center.y = CGRectGetMaxY(contentFrame);
break;
}
return center;
}

View File

@@ -308,6 +308,21 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)mapView:(MGLMapView *)mapView didChangeUserTrackingMode:(MGLUserTrackingMode)mode animated:(BOOL)animated;
/**
Returns a screen coordinate at which to position the user location annotation.
This coordinate is relative to the map view’s origin after applying the map view’s
content insets.
When unimplemented, the user location annotation is aligned within the center of
the map view with respect to the content insets.
This method will override any values set by `MGLMapView.userLocationVerticalAlignment`
or `-[MGLMapView setUserLocationVerticalAlignment:]`.
@param mapView The map view that is tracking the user's location.
*/
- (CGPoint)mapViewUserLocationAnchorPoint:(MGLMapView *)mapView;
#pragma mark Managing the Appearance of Annotations
/**

View File

@@ -92,4 +92,6 @@ extension MGLMapViewDelegateIntegrationTests: MGLMapViewDelegate {
func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera) -> Bool { return false }
func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera, reason: MGLCameraChangeReason) -> Bool { return false }
func mapViewUserLocationAnchorPoint(_ mapView: MGLMapView) -> CGPoint { return CGPoint(x: 100, y: 100) }
}