[ios] Fixes an issue that caused the ornaments ignore contentInset property. (#15584)
* [ios] Add mapView content inset tests. * [ios] Fix an issue that caused the ornaments ignore the contentInsets. Fixed an issue that caused ornaments ignore the contentInset. Added a new property automaticallyAdjustContentInset that has the same purpose as UIViewController. automaticallyAdjustsScrollViewInsets. This was changed due to the latter being deprecated. * [ios] Fix automaticallyAdjustsScrollViewInsets legacy behavior. The property automaticallyAdjustsScrollViewInsets overrode automaticallyAdjustsScrollViewInsets which caused a breaking change. This is fixed to consider the legacy property when calculating the content insets and added tests for both cases. * [ios] Fix the contentInset value after adding padding to the camera. Fixed an issue that caused a discrepancy between the contentInset in MGLMapView and the padding in the transformation state. When padding is passed through methods such as setCamera it’s persisted. This fix resets the contentInsets. * [ios] Fix pinch test. * [ios] Update automaticallyAdjustsScrollViewInsets name and documentation. * [ios] Update changelog.
This commit is contained in:
committed by
GitHub
parent
33a70100b8
commit
5c565a5e51
@@ -14,6 +14,9 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
|
||||
|
||||
* Added `-[MGLMapSnapshotOverlay coordinateForPoint:]` and `-[MGLMapSnapshotOverlay pointForCoordinate:]` to convert between context and map coordinates, mirroring those of `MGLMapSnapshot`. ([#15746](https://github.com/mapbox/mapbox-gl-native/pull/15746))
|
||||
* Suppress network requests for expired tiles update, if these tiles are invisible. ([#15741](https://github.com/mapbox/mapbox-gl-native/pull/15741))
|
||||
* Fixed an issue that cause the ornaments to ignore `MGLMapView.contentInset` property. ([#15584](https://github.com/mapbox/mapbox-gl-native/pull/15584))
|
||||
* Fixed an issue that cause `-[MGLMapView setCamere:withDuration:animationTimingFunction:edgePadding:completionHandler:]` persist the value of `edgePadding`. ([#15584](https://github.com/mapbox/mapbox-gl-native/pull/15584))
|
||||
* Added `MGLMapView.automaticallyAdjustsContentInset` property that indicates if wether the map view should automatically adjust its content insets. ([#15584](https://github.com/mapbox/mapbox-gl-native/pull/15584))
|
||||
* Fixed an issue that caused `MGLScaleBar` to have an incorrect size when resizing or rotating. ([#15703](https://github.com/mapbox/mapbox-gl-native/pull/15703))
|
||||
|
||||
## 5.4.0 - September 25, 2019
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
170C437D2029D97900863DF0 /* MGLHeatmapStyleLayerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 170C43792028D49800863DF0 /* MGLHeatmapStyleLayerTests.mm */; };
|
||||
1753ED421E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
|
||||
1753ED431E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
|
||||
1F0196AA23174B0700F5C819 /* MGLMapViewContentInsetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F0196A923174B0700F5C819 /* MGLMapViewContentInsetTests.m */; };
|
||||
1F06668A1EC64F8E001C16D7 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0666881EC64F8E001C16D7 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
1F06668D1EC64F8E001C16D7 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F0666891EC64F8E001C16D7 /* MGLLight.mm */; };
|
||||
1F26B6C120E189C9007BCC21 /* MBXCustomLocationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F26B6C020E189C9007BCC21 /* MBXCustomLocationViewController.m */; };
|
||||
@@ -50,6 +51,7 @@
|
||||
1F7454A91ED08AB400021D39 /* MGLLightTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454A61ED08AB400021D39 /* MGLLightTest.mm */; };
|
||||
1F8A59F72165326D004DFE75 /* sideload_sat.db in Resources */ = {isa = PBXBuildFile; fileRef = 1F8A59F62165326C004DFE75 /* sideload_sat.db */; };
|
||||
1F8A59F821653275004DFE75 /* sideload_sat.db in Resources */ = {isa = PBXBuildFile; fileRef = 1F8A59F62165326C004DFE75 /* sideload_sat.db */; };
|
||||
1F8E8A81233A9FD9009B51ED /* MGLMapViewGestureRecognizerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F8E8A80233A9FD9009B51ED /* MGLMapViewGestureRecognizerTests.mm */; };
|
||||
1F95931D1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */; };
|
||||
1FC4817D2098CBC0000D09B4 /* NSPredicate+MGLPrivateAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FC4817B2098CBC0000D09B4 /* NSPredicate+MGLPrivateAdditions.h */; };
|
||||
1FC4817F2098CD80000D09B4 /* NSPredicate+MGLPrivateAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FC4817B2098CBC0000D09B4 /* NSPredicate+MGLPrivateAdditions.h */; };
|
||||
@@ -899,6 +901,7 @@
|
||||
170C43782028D49800863DF0 /* MGLHeatmapColorTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLHeatmapColorTests.mm; path = ../../darwin/test/MGLHeatmapColorTests.mm; sourceTree = "<group>"; };
|
||||
170C43792028D49800863DF0 /* MGLHeatmapStyleLayerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLHeatmapStyleLayerTests.mm; path = ../../darwin/test/MGLHeatmapStyleLayerTests.mm; sourceTree = "<group>"; };
|
||||
1753ED411E53CE6F00A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = "<group>"; };
|
||||
1F0196A923174B0700F5C819 /* MGLMapViewContentInsetTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLMapViewContentInsetTests.m; sourceTree = "<group>"; };
|
||||
1F0666881EC64F8E001C16D7 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = "<group>"; };
|
||||
1F0666891EC64F8E001C16D7 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = "<group>"; };
|
||||
1F26B6BF20E189C9007BCC21 /* MBXCustomLocationViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBXCustomLocationViewController.h; sourceTree = "<group>"; };
|
||||
@@ -910,6 +913,7 @@
|
||||
1F7454941ECD450D00021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = "<group>"; };
|
||||
1F7454A61ED08AB400021D39 /* MGLLightTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLLightTest.mm; path = ../../darwin/test/MGLLightTest.mm; sourceTree = "<group>"; };
|
||||
1F8A59F62165326C004DFE75 /* sideload_sat.db */ = {isa = PBXFileReference; lastKnownFileType = file; name = sideload_sat.db; path = ../../../test/fixtures/offline_database/sideload_sat.db; sourceTree = "<group>"; };
|
||||
1F8E8A80233A9FD9009B51ED /* MGLMapViewGestureRecognizerTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLMapViewGestureRecognizerTests.mm; sourceTree = "<group>"; };
|
||||
1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLNSDateAdditionsTests.mm; path = ../../darwin/test/MGLNSDateAdditionsTests.mm; sourceTree = "<group>"; };
|
||||
1FC4817B2098CBC0000D09B4 /* NSPredicate+MGLPrivateAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSPredicate+MGLPrivateAdditions.h"; sourceTree = "<group>"; };
|
||||
1FCAE2A020B872A400C577DD /* MGLLocationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLLocationManager.h; sourceTree = "<group>"; };
|
||||
@@ -2084,7 +2088,9 @@
|
||||
DA5DB1291FABF1EE001C2326 /* MGLMapAccessibilityElementTests.m */,
|
||||
DA695425215B1E75002041A4 /* MGLMapCameraTests.m */,
|
||||
96E6145522CC135200109F14 /* MGLMapViewCompassViewTests.mm */,
|
||||
1F0196A923174B0700F5C819 /* MGLMapViewContentInsetTests.m */,
|
||||
96ED34DD22374C0900E9FCA9 /* MGLMapViewDirectionTests.mm */,
|
||||
1F8E8A80233A9FD9009B51ED /* MGLMapViewGestureRecognizerTests.mm */,
|
||||
16376B481FFEED010000563E /* MGLMapViewLayoutTests.m */,
|
||||
96381C0122C6F3950053497D /* MGLMapViewPitchTests.m */,
|
||||
9658C154204761FC00D8A674 /* MGLMapViewScaleBarTests.m */,
|
||||
@@ -3322,11 +3328,13 @@
|
||||
920A3E5D1E6F995200C16EFC /* MGLSourceQueryTests.m in Sources */,
|
||||
DA5DB12A1FABF1EE001C2326 /* MGLMapAccessibilityElementTests.m in Sources */,
|
||||
96ED34DE22374C0900E9FCA9 /* MGLMapViewDirectionTests.mm in Sources */,
|
||||
1F0196AA23174B0700F5C819 /* MGLMapViewContentInsetTests.m in Sources */,
|
||||
FAE1CDCB1E9D79CB00C40B5B /* MGLFillExtrusionStyleLayerTests.mm in Sources */,
|
||||
DA35A2AA1CCA058D00E826B2 /* MGLCoordinateFormatterTests.m in Sources */,
|
||||
357579831D502AE6000B822E /* MGLRasterStyleLayerTests.mm in Sources */,
|
||||
3502D6CC22AE88D5006BDFCE /* MGLAccountManagerTests.m in Sources */,
|
||||
DAF25720201902BC00367EF5 /* MGLHillshadeStyleLayerTests.mm in Sources */,
|
||||
1F8E8A81233A9FD9009B51ED /* MGLMapViewGestureRecognizerTests.mm in Sources */,
|
||||
353D23961D0B0DFE002BE09D /* MGLAnnotationViewTests.m in Sources */,
|
||||
DA0CD5901CF56F6A00A5F5A5 /* MGLFeatureTests.mm in Sources */,
|
||||
556660D81E1D085500E2C41B /* MGLVersionNumber.m in Sources */,
|
||||
|
||||
@@ -286,6 +286,17 @@ MGL_EXPORT
|
||||
*/
|
||||
- (IBAction)reloadStyle:(nullable id)sender;
|
||||
|
||||
/**
|
||||
A boolean value that indicates if whether the map view should automatically
|
||||
adjust its content insets.
|
||||
|
||||
When this property is set to `YES` the map automatically updates its
|
||||
`contentInset` property to account for any area not covered by navigation bars,
|
||||
tab bars, toolbars, and other ancestors that obscure the map view.
|
||||
|
||||
*/
|
||||
@property (assign) BOOL automaticallyAdjustsContentInset;
|
||||
|
||||
/**
|
||||
A Boolean value indicating whether the map may display scale information.
|
||||
|
||||
@@ -1308,10 +1319,13 @@ MGL_EXPORT
|
||||
view’s frame. Otherwise, those properties are inset, excluding part of the
|
||||
frame from the viewport. For instance, if the only the top edge is inset, the
|
||||
map center is effectively shifted downward.
|
||||
|
||||
|
||||
When the map view’s superview is an instance of `UIViewController` whose
|
||||
`automaticallyAdjustsScrollViewInsets` property is `YES`, the value of this
|
||||
property may be overridden at any time.
|
||||
|
||||
The usage of `automaticallyAdjustsScrollViewInsets` has been deprecated
|
||||
use the map view’s property `MGLMapView.automaticallyAdjustsContentInset`instead.
|
||||
|
||||
Changing the value of this property updates the map view immediately. If you
|
||||
want to animate the change, use the `-setContentInset:animated:completionHandler:`
|
||||
@@ -1333,6 +1347,9 @@ MGL_EXPORT
|
||||
`automaticallyAdjustsScrollViewInsets` property is `YES`, the value of this
|
||||
property may be overridden at any time.
|
||||
|
||||
The usage of `automaticallyAdjustsScrollViewInsets` has been deprecated
|
||||
use the map view’s property `MGLMapView.automaticallyAdjustsContentInset`instead.
|
||||
|
||||
To specify a completion handler to execute after the animation finishes, use
|
||||
the `-setContentInset:animated:completionHandler:` method.
|
||||
|
||||
@@ -1357,6 +1374,9 @@ MGL_EXPORT
|
||||
When the map view’s superview is an instance of `UIViewController` whose
|
||||
`automaticallyAdjustsScrollViewInsets` property is `YES`, the value of this
|
||||
property may be overridden at any time.
|
||||
|
||||
The usage of `automaticallyAdjustsScrollViewInsets` has been deprecated
|
||||
use the map view’s property `MGLMapView.automaticallyAdjustsContentInset`instead.
|
||||
|
||||
@param contentInset The new values to inset the content by.
|
||||
@param animated Specify `YES` if you want the map view to animate the change to
|
||||
|
||||
@@ -274,6 +274,11 @@ public:
|
||||
/// Tilt gesture recognizer helper
|
||||
@property (nonatomic, assign) CGPoint dragGestureMiddlePoint;
|
||||
|
||||
/// This property is used to keep track of the view's safe edge insets
|
||||
/// and calculate the ornament's position
|
||||
@property (nonatomic, assign) UIEdgeInsets safeMapViewContentInsets;
|
||||
@property (nonatomic, strong) NSNumber *automaticallyAdjustContentInsetHolder;
|
||||
|
||||
- (mbgl::Map &)mbglMap;
|
||||
|
||||
@end
|
||||
@@ -518,6 +523,14 @@ public:
|
||||
_annotationViewReuseQueueByIdentifier = [NSMutableDictionary dictionary];
|
||||
_selectedAnnotationTag = MGLAnnotationTagNotFound;
|
||||
_annotationsNearbyLastTap = {};
|
||||
|
||||
// TODO: This warning should be removed when automaticallyAdjustsScrollViewInsets is removed from
|
||||
// the UIViewController api.
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSLog(@"%@ WARNING UIViewController.automaticallyAdjustsScrollViewInsets is deprecated use MGLMapView.automaticallyAdjustContentInset instead.",
|
||||
NSStringFromClass(self.class));
|
||||
});
|
||||
|
||||
// setup logo
|
||||
//
|
||||
@@ -832,23 +845,46 @@ public:
|
||||
size:(CGSize)size
|
||||
margins:(CGPoint)margins {
|
||||
NSMutableArray *updatedConstraints = [NSMutableArray array];
|
||||
UIEdgeInsets inset = UIEdgeInsetsZero;
|
||||
|
||||
BOOL automaticallyAdjustContentInset;
|
||||
if (_automaticallyAdjustContentInsetHolder) {
|
||||
automaticallyAdjustContentInset = _automaticallyAdjustContentInsetHolder.boolValue;
|
||||
} else {
|
||||
UIViewController *viewController = [self rootViewController];
|
||||
automaticallyAdjustContentInset = viewController.automaticallyAdjustsScrollViewInsets;
|
||||
}
|
||||
|
||||
if (! automaticallyAdjustContentInset) {
|
||||
inset = UIEdgeInsetsMake(self.contentInset.top - self.safeMapViewContentInsets.top,
|
||||
self.contentInset.left - self.safeMapViewContentInsets.left,
|
||||
self.contentInset.bottom - self.safeMapViewContentInsets.bottom,
|
||||
self.contentInset.right - self.safeMapViewContentInsets.right);
|
||||
|
||||
// makes sure the insets don't have negative values that could hide the ornaments
|
||||
// thus violating our ToS
|
||||
inset = UIEdgeInsetsMake(fmaxf(inset.top, 0),
|
||||
fmaxf(inset.left, 0),
|
||||
fmaxf(inset.bottom, 0),
|
||||
fmaxf(inset.right, 0));
|
||||
}
|
||||
|
||||
switch (position) {
|
||||
case MGLOrnamentPositionTopLeft:
|
||||
[updatedConstraints addObject:[view.topAnchor constraintEqualToAnchor:self.mgl_safeTopAnchor constant:margins.y]];
|
||||
[updatedConstraints addObject:[view.leadingAnchor constraintEqualToAnchor:self.mgl_safeLeadingAnchor constant:margins.x]];
|
||||
[updatedConstraints addObject:[view.topAnchor constraintEqualToAnchor:self.mgl_safeTopAnchor constant:margins.y + inset.top]];
|
||||
[updatedConstraints addObject:[view.leadingAnchor constraintEqualToAnchor:self.mgl_safeLeadingAnchor constant:margins.x + inset.left]];
|
||||
break;
|
||||
case MGLOrnamentPositionTopRight:
|
||||
[updatedConstraints addObject:[view.topAnchor constraintEqualToAnchor:self.mgl_safeTopAnchor constant:margins.y]];
|
||||
[updatedConstraints addObject:[self.mgl_safeTrailingAnchor constraintEqualToAnchor:view.trailingAnchor constant:margins.x]];
|
||||
[updatedConstraints addObject:[view.topAnchor constraintEqualToAnchor:self.mgl_safeTopAnchor constant:margins.y + inset.top]];
|
||||
[updatedConstraints addObject:[self.mgl_safeTrailingAnchor constraintEqualToAnchor:view.trailingAnchor constant:margins.x + inset.right]];
|
||||
break;
|
||||
case MGLOrnamentPositionBottomLeft:
|
||||
[updatedConstraints addObject:[self.mgl_safeBottomAnchor constraintEqualToAnchor:view.bottomAnchor constant:margins.y]];
|
||||
[updatedConstraints addObject:[view.leadingAnchor constraintEqualToAnchor:self.mgl_safeLeadingAnchor constant:margins.x]];
|
||||
[updatedConstraints addObject:[self.mgl_safeBottomAnchor constraintEqualToAnchor:view.bottomAnchor constant:margins.y + inset.bottom]];
|
||||
[updatedConstraints addObject:[view.leadingAnchor constraintEqualToAnchor:self.mgl_safeLeadingAnchor constant:margins.x + inset.left]];
|
||||
break;
|
||||
case MGLOrnamentPositionBottomRight:
|
||||
[updatedConstraints addObject:[self.mgl_safeBottomAnchor constraintEqualToAnchor:view.bottomAnchor constant:margins.y]];
|
||||
[updatedConstraints addObject: [self.mgl_safeTrailingAnchor constraintEqualToAnchor:view.trailingAnchor constant:margins.x]];
|
||||
[updatedConstraints addObject:[self.mgl_safeBottomAnchor constraintEqualToAnchor:view.bottomAnchor constant:margins.y + inset.bottom]];
|
||||
[updatedConstraints addObject: [self.mgl_safeTrailingAnchor constraintEqualToAnchor:view.trailingAnchor constant:margins.x + inset.right]];
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -968,6 +1004,38 @@ public:
|
||||
/// Updates `contentInset` to reflect the current window geometry.
|
||||
- (void)adjustContentInset
|
||||
{
|
||||
UIEdgeInsets adjustedContentInsets = UIEdgeInsetsZero;
|
||||
UIViewController *viewController = [self rootViewController];
|
||||
BOOL automaticallyAdjustContentInset;
|
||||
if (@available(iOS 11.0, *))
|
||||
{
|
||||
adjustedContentInsets = self.safeAreaInsets;
|
||||
|
||||
} else {
|
||||
adjustedContentInsets.top = viewController.topLayoutGuide.length;
|
||||
CGFloat bottomPoint = CGRectGetMaxY(viewController.view.bounds) -
|
||||
(CGRectGetMaxY(viewController.view.bounds)
|
||||
- viewController.bottomLayoutGuide.length);
|
||||
adjustedContentInsets.bottom = bottomPoint;
|
||||
|
||||
}
|
||||
|
||||
if (_automaticallyAdjustContentInsetHolder) {
|
||||
automaticallyAdjustContentInset = _automaticallyAdjustContentInsetHolder.boolValue;
|
||||
} else {
|
||||
automaticallyAdjustContentInset = viewController.automaticallyAdjustsScrollViewInsets;
|
||||
}
|
||||
|
||||
self.safeMapViewContentInsets = adjustedContentInsets;
|
||||
if ( ! automaticallyAdjustContentInset)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.contentInset = adjustedContentInsets;
|
||||
}
|
||||
|
||||
- (UIViewController *)rootViewController {
|
||||
// We could crawl all the way up the responder chain using
|
||||
// -viewControllerForLayoutGuides, but an intervening view means that any
|
||||
// manual contentInset should not be overridden; something other than the
|
||||
@@ -983,25 +1051,16 @@ public:
|
||||
// This map view is an immediate child of a view controller’s content view.
|
||||
viewController = (UIViewController *)self.superview.nextResponder;
|
||||
}
|
||||
return viewController;
|
||||
}
|
||||
|
||||
if ( ! viewController.automaticallyAdjustsScrollViewInsets)
|
||||
{
|
||||
return;
|
||||
}
|
||||
- (void)setAutomaticallyAdjustsContentInset:(BOOL)automaticallyAdjustsContentInset {
|
||||
MGLLogDebug(@"Setting automaticallyAdjustsContentInset: %@", MGLStringFromBOOL(automaticallyAdjustsContentInset));
|
||||
_automaticallyAdjustContentInsetHolder = [NSNumber numberWithBool:automaticallyAdjustsContentInset];
|
||||
}
|
||||
|
||||
UIEdgeInsets contentInset = UIEdgeInsetsZero;
|
||||
CGPoint topPoint = CGPointMake(0, viewController.topLayoutGuide.length);
|
||||
contentInset.top = [self convertPoint:topPoint fromView:viewController.view].y;
|
||||
CGPoint bottomPoint = CGPointMake(0, CGRectGetMaxY(viewController.view.bounds)
|
||||
- viewController.bottomLayoutGuide.length);
|
||||
contentInset.bottom = (CGRectGetMaxY(self.bounds)
|
||||
- [self convertPoint:bottomPoint fromView:viewController.view].y);
|
||||
|
||||
// Negative insets are invalid, replace with 0.
|
||||
contentInset.top = fmaxf(contentInset.top, 0);
|
||||
contentInset.bottom = fmaxf(contentInset.bottom, 0);
|
||||
|
||||
self.contentInset = contentInset;
|
||||
- (BOOL)automaticallyAdjustsContentInset {
|
||||
return _automaticallyAdjustContentInsetHolder.boolValue;
|
||||
}
|
||||
|
||||
- (void)setContentInset:(UIEdgeInsets)contentInset
|
||||
@@ -1701,7 +1760,10 @@ public:
|
||||
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
self.mbglMap.jumpTo(mbgl::CameraOptions().withZoom(newZoom).withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }));
|
||||
self.mbglMap.jumpTo(mbgl::CameraOptions()
|
||||
.withZoom(newZoom)
|
||||
.withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y })
|
||||
.withPadding(MGLEdgeInsetsFromNSEdgeInsets(self.contentInset)));
|
||||
|
||||
// The gesture recognizer only reports the gesture’s current center
|
||||
// point, so use the previous center point to anchor the transition.
|
||||
@@ -1759,7 +1821,10 @@ public:
|
||||
{
|
||||
if (drift)
|
||||
{
|
||||
self.mbglMap.easeTo(mbgl::CameraOptions().withZoom(zoom).withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }), MGLDurationFromTimeInterval(duration));
|
||||
self.mbglMap.easeTo(mbgl::CameraOptions()
|
||||
.withZoom(zoom)
|
||||
.withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y })
|
||||
.withPadding(MGLEdgeInsetsFromNSEdgeInsets(self.contentInset)), MGLDurationFromTimeInterval(duration));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1824,7 +1889,8 @@ public:
|
||||
{
|
||||
self.mbglMap.jumpTo(mbgl::CameraOptions()
|
||||
.withBearing(newDegrees)
|
||||
.withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y}));
|
||||
.withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y})
|
||||
.withPadding(MGLEdgeInsetsFromNSEdgeInsets(self.contentInset)));
|
||||
}
|
||||
|
||||
[self cameraIsChanging];
|
||||
@@ -1865,7 +1931,8 @@ public:
|
||||
{
|
||||
self.mbglMap.easeTo(mbgl::CameraOptions()
|
||||
.withBearing(newDegrees)
|
||||
.withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }),
|
||||
.withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y })
|
||||
.withPadding(MGLEdgeInsetsFromNSEdgeInsets(self.contentInset)),
|
||||
MGLDurationFromTimeInterval(decelerationRate));
|
||||
|
||||
[self notifyGestureDidEndWithDrift:YES];
|
||||
@@ -1993,7 +2060,10 @@ public:
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
mbgl::ScreenCoordinate center(gesturePoint.x, gesturePoint.y);
|
||||
self.mbglMap.easeTo(mbgl::CameraOptions().withZoom(newZoom).withAnchor(center), MGLDurationFromTimeInterval(MGLAnimationDuration));
|
||||
self.mbglMap.easeTo(mbgl::CameraOptions()
|
||||
.withZoom(newZoom)
|
||||
.withAnchor(center)
|
||||
.withPadding(MGLEdgeInsetsFromNSEdgeInsets(self.contentInset)), MGLDurationFromTimeInterval(MGLAnimationDuration));
|
||||
|
||||
__weak MGLMapView *weakSelf = self;
|
||||
|
||||
@@ -2031,7 +2101,10 @@ public:
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
mbgl::ScreenCoordinate center(gesturePoint.x, gesturePoint.y);
|
||||
self.mbglMap.easeTo(mbgl::CameraOptions().withZoom(newZoom).withAnchor(center), MGLDurationFromTimeInterval(MGLAnimationDuration));
|
||||
self.mbglMap.easeTo(mbgl::CameraOptions()
|
||||
.withZoom(newZoom)
|
||||
.withAnchor(center)
|
||||
.withPadding(MGLEdgeInsetsFromNSEdgeInsets(self.contentInset)), MGLDurationFromTimeInterval(MGLAnimationDuration));
|
||||
|
||||
__weak MGLMapView *weakSelf = self;
|
||||
|
||||
@@ -2073,7 +2146,10 @@ public:
|
||||
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
self.mbglMap.jumpTo(mbgl::CameraOptions().withZoom(newZoom).withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }));
|
||||
self.mbglMap.jumpTo(mbgl::CameraOptions()
|
||||
.withZoom(newZoom)
|
||||
.withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y })
|
||||
.withPadding(MGLEdgeInsetsFromNSEdgeInsets(self.contentInset)));
|
||||
}
|
||||
|
||||
[self cameraIsChanging];
|
||||
@@ -2140,7 +2216,8 @@ public:
|
||||
{
|
||||
self.mbglMap.jumpTo(mbgl::CameraOptions()
|
||||
.withPitch(pitchNew)
|
||||
.withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }));
|
||||
.withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y })
|
||||
.withPadding(MGLEdgeInsetsFromNSEdgeInsets(self.contentInset)));
|
||||
}
|
||||
|
||||
[self cameraIsChanging];
|
||||
@@ -3200,7 +3277,10 @@ public:
|
||||
centerPoint = self.userLocationAnnotationViewCenter;
|
||||
}
|
||||
double newZoom = round(self.zoomLevel) + log2(scaleFactor);
|
||||
self.mbglMap.jumpTo(mbgl::CameraOptions().withZoom(newZoom).withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }));
|
||||
self.mbglMap.jumpTo(mbgl::CameraOptions()
|
||||
.withZoom(newZoom)
|
||||
.withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y })
|
||||
.withPadding(MGLEdgeInsetsFromNSEdgeInsets(self.contentInset)));
|
||||
[self unrotateIfNeededForGesture];
|
||||
|
||||
_accessibilityValueAnnouncementIsPending = YES;
|
||||
|
||||
177
platform/ios/test/MGLMapViewContentInsetTests.m
Normal file
177
platform/ios/test/MGLMapViewContentInsetTests.m
Normal file
@@ -0,0 +1,177 @@
|
||||
#import <Mapbox/Mapbox.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface MGLMapViewContentInsetTests : XCTestCase <MGLMapViewDelegate>
|
||||
|
||||
@property (nonatomic) MGLMapView *mapView;
|
||||
@property (nonatomic) UIWindow *window;
|
||||
@property (nonatomic) UIViewController *viewController;
|
||||
@property (nonatomic) XCTestExpectation *styleLoadingExpectation;
|
||||
@property (assign) CGRect screenBounds;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MGLMapViewContentInsetTests
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
|
||||
[MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
|
||||
NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
|
||||
self.screenBounds = UIScreen.mainScreen.bounds;
|
||||
self.mapView = [[MGLMapView alloc] initWithFrame:self.screenBounds styleURL:styleURL];
|
||||
self.mapView.zoomLevel = 16;
|
||||
self.mapView.delegate = self;
|
||||
|
||||
self.viewController = [[UIViewController alloc] init];
|
||||
self.viewController.view = [[UIView alloc] initWithFrame:self.screenBounds];
|
||||
[self.viewController.view addSubview:self.mapView];
|
||||
self.window = [[UIWindow alloc] initWithFrame:self.screenBounds];
|
||||
[self.window addSubview:self.viewController.view];
|
||||
[self.window makeKeyAndVisible];
|
||||
|
||||
if (!self.mapView.style) {
|
||||
_styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."];
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
|
||||
XCTAssertNotNil(mapView.style);
|
||||
XCTAssertEqual(mapView.style, style);
|
||||
|
||||
[_styleLoadingExpectation fulfill];
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
self.mapView = nil;
|
||||
[MGLAccountManager setAccessToken:nil];
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)testContentInsetCenter {
|
||||
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(1.0, 5.0);
|
||||
self.mapView.centerCoordinate = center;
|
||||
XCTAssertEqualWithAccuracy(self.mapView.centerCoordinate.latitude, center.latitude, 0.01);
|
||||
XCTAssertEqualWithAccuracy(self.mapView.centerCoordinate.longitude, center.longitude, 0.01);
|
||||
|
||||
CGPoint centerPoint = [self.mapView convertCoordinate:center toPointToView:self.mapView];
|
||||
|
||||
XCTAssertEqualWithAccuracy(centerPoint.x, self.screenBounds.size.width/2, 0.01);
|
||||
XCTAssertEqualWithAccuracy(centerPoint.y, self.screenBounds.size.height/2, 0.01);
|
||||
|
||||
// shifting contentInset should keep the same centerCoordinate but shift the screen
|
||||
// center point accordingly
|
||||
UIEdgeInsets contentInset = UIEdgeInsetsMake(50.0, 10.0, 10.0, 30.0);
|
||||
self.mapView.contentInset = contentInset;
|
||||
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
XCTAssertEqualWithAccuracy(self.mapView.centerCoordinate.latitude, center.latitude, 0.01);
|
||||
XCTAssertEqualWithAccuracy(self.mapView.centerCoordinate.longitude, center.longitude, 0.01);
|
||||
CGPoint shiftedPoint = [self.mapView convertCoordinate:center toPointToView:self.mapView];
|
||||
CGPoint expectedShiftedPoint = CGPointMake((self.screenBounds.size.width/2) + ((contentInset.left - contentInset.right) / 2 ),
|
||||
(self.screenBounds.size.height/2) + ((contentInset.top - contentInset.bottom) / 2));
|
||||
XCTAssertEqualWithAccuracy(shiftedPoint.x, expectedShiftedPoint.x, 0.01);
|
||||
XCTAssertEqualWithAccuracy(shiftedPoint.y, expectedShiftedPoint.y, 0.01);
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (void)testContentInsetOrnaments {
|
||||
CGFloat margin = 8;
|
||||
self.mapView.contentInset = UIEdgeInsetsZero;
|
||||
UIView *scaleBar = self.mapView.scaleBar;
|
||||
CGPoint expectedScaleBarOrigin = CGPointMake(margin, margin);
|
||||
XCTAssertTrue(CGPointEqualToPoint(scaleBar.frame.origin, expectedScaleBarOrigin));
|
||||
|
||||
UIView *compassView = self.mapView.compassView;
|
||||
CGFloat x = self.screenBounds.size.width - compassView.bounds.size.width - margin;
|
||||
CGPoint expectedCompassOrigin = CGPointMake(x, margin);
|
||||
XCTAssertTrue(CGPointEqualToPoint(compassView.frame.origin, expectedCompassOrigin));
|
||||
|
||||
UIView *logoView = self.mapView.logoView;
|
||||
CGFloat y = self.screenBounds.size.height - logoView.bounds.size.height - margin;
|
||||
CGPoint expectedLogoOrigin = CGPointMake(margin, y);
|
||||
XCTAssertTrue(CGPointEqualToPoint(logoView.frame.origin, expectedLogoOrigin));
|
||||
|
||||
UIView *attributionView = self.mapView.attributionButton;
|
||||
x = self.screenBounds.size.width - attributionView.bounds.size.width - margin;
|
||||
y = self.screenBounds.size.height - attributionView.bounds.size.height - margin;
|
||||
CGPoint expectedAttributionOrigin = CGPointMake(x, y);
|
||||
XCTAssertTrue(CGPointEqualToPoint(attributionView.frame.origin, expectedAttributionOrigin));
|
||||
|
||||
UIEdgeInsets insets = UIEdgeInsetsMake(15, 10, 20, 5);
|
||||
self.viewController.automaticallyAdjustsScrollViewInsets = NO;
|
||||
self.mapView.contentInset = insets;
|
||||
|
||||
[self.mapView setNeedsLayout];
|
||||
[self.mapView layoutIfNeeded];
|
||||
|
||||
expectedScaleBarOrigin = CGPointMake(insets.left + self.mapView.scaleBarMargins.x, insets.top + self.mapView.scaleBarMargins.y);
|
||||
XCTAssertTrue(CGPointEqualToPoint(scaleBar.frame.origin, expectedScaleBarOrigin));
|
||||
|
||||
x = self.screenBounds.size.width - compassView.bounds.size.width - insets.right - self.mapView.compassViewMargins.x;
|
||||
expectedCompassOrigin = CGPointMake(x, insets.top + self.mapView.compassViewMargins.y);
|
||||
XCTAssertTrue(CGPointEqualToPoint(compassView.frame.origin, expectedCompassOrigin));
|
||||
|
||||
y = self.screenBounds.size.height - logoView.bounds.size.height - insets.bottom - self.mapView.logoViewMargins.y;
|
||||
expectedLogoOrigin = CGPointMake(insets.left + self.mapView.logoViewMargins.x, y);
|
||||
XCTAssertTrue(CGPointEqualToPoint(logoView.frame.origin, expectedLogoOrigin));
|
||||
|
||||
x = self.screenBounds.size.width - attributionView.bounds.size.width - insets.right - self.mapView.attributionButtonMargins.x;
|
||||
y = self.screenBounds.size.height - attributionView.bounds.size.height - insets.bottom - self.mapView.attributionButtonMargins.y;
|
||||
expectedAttributionOrigin = CGPointMake(x, y);
|
||||
XCTAssertTrue(CGPointEqualToPoint(attributionView.frame.origin, expectedAttributionOrigin));
|
||||
|
||||
// tests that passing negative values result in a 0 inset value
|
||||
insets = UIEdgeInsetsMake(-100, -100, -100, -100);
|
||||
self.mapView.contentInset = insets;
|
||||
|
||||
[self.mapView setNeedsLayout];
|
||||
[self.mapView layoutIfNeeded];
|
||||
|
||||
expectedScaleBarOrigin = CGPointMake(margin, margin);
|
||||
XCTAssertTrue(CGPointEqualToPoint(scaleBar.frame.origin, expectedScaleBarOrigin));
|
||||
|
||||
x = self.screenBounds.size.width - compassView.bounds.size.width - margin;
|
||||
expectedCompassOrigin = CGPointMake(x, margin);
|
||||
XCTAssertTrue(CGPointEqualToPoint(compassView.frame.origin, expectedCompassOrigin));
|
||||
|
||||
y = self.screenBounds.size.height - logoView.bounds.size.height - margin;
|
||||
expectedLogoOrigin = CGPointMake(margin, y);
|
||||
XCTAssertTrue(CGPointEqualToPoint(logoView.frame.origin, expectedLogoOrigin));
|
||||
|
||||
x = self.screenBounds.size.width - attributionView.bounds.size.width - margin;
|
||||
y = self.screenBounds.size.height - attributionView.bounds.size.height - margin;
|
||||
expectedAttributionOrigin = CGPointMake(x, y);
|
||||
XCTAssertTrue(CGPointEqualToPoint(attributionView.frame.origin, expectedAttributionOrigin));
|
||||
|
||||
self.mapView.automaticallyAdjustsContentInset = YES;
|
||||
insets = UIEdgeInsetsMake(100, 100, 100, 100);
|
||||
self.mapView.contentInset = insets;
|
||||
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, insets));
|
||||
|
||||
[self.mapView setNeedsLayout];
|
||||
[self.mapView layoutIfNeeded];
|
||||
|
||||
// when automaticallyAdjustsContentInset = YES the content insets should be overwriten
|
||||
XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, insets));
|
||||
|
||||
expectedScaleBarOrigin = CGPointMake(margin, margin);
|
||||
XCTAssertTrue(CGPointEqualToPoint(scaleBar.frame.origin, expectedScaleBarOrigin));
|
||||
|
||||
x = self.screenBounds.size.width - compassView.bounds.size.width - margin;
|
||||
expectedCompassOrigin = CGPointMake(x, margin);
|
||||
XCTAssertTrue(CGPointEqualToPoint(compassView.frame.origin, expectedCompassOrigin));
|
||||
|
||||
y = self.screenBounds.size.height - logoView.bounds.size.height - margin;
|
||||
expectedLogoOrigin = CGPointMake(margin, y);
|
||||
XCTAssertTrue(CGPointEqualToPoint(logoView.frame.origin, expectedLogoOrigin));
|
||||
|
||||
x = self.screenBounds.size.width - attributionView.bounds.size.width - margin;
|
||||
y = self.screenBounds.size.height - attributionView.bounds.size.height - margin;
|
||||
expectedAttributionOrigin = CGPointMake(x, y);
|
||||
XCTAssertTrue(CGPointEqualToPoint(attributionView.frame.origin, expectedAttributionOrigin));
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
280
platform/ios/test/MGLMapViewGestureRecognizerTests.mm
Normal file
280
platform/ios/test/MGLMapViewGestureRecognizerTests.mm
Normal file
@@ -0,0 +1,280 @@
|
||||
#import <Mapbox/Mapbox.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "../../darwin/src/MGLGeometry_Private.h"
|
||||
#import "MGLMockGestureRecognizers.h"
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/map/camera.hpp>
|
||||
|
||||
@interface MGLMapView (MGLMapViewGestureRecognizerTests)
|
||||
|
||||
- (mbgl::Map &)mbglMap;
|
||||
|
||||
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch;
|
||||
- (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate;
|
||||
- (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap;
|
||||
- (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap;
|
||||
- (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom;
|
||||
- (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag;
|
||||
|
||||
@end
|
||||
|
||||
@interface MGLMapViewGestureRecognizerTests : XCTestCase <MGLMapViewDelegate>
|
||||
|
||||
@property (nonatomic) MGLMapView *mapView;
|
||||
@property (nonatomic) UIWindow *window;
|
||||
@property (nonatomic) UIViewController *viewController;
|
||||
@property (nonatomic) XCTestExpectation *styleLoadingExpectation;
|
||||
@property (nonatomic) XCTestExpectation *twoFingerExpectation;
|
||||
@property (nonatomic) XCTestExpectation *quickZoomExpectation;
|
||||
@property (nonatomic) XCTestExpectation *doubleTapExpectation;
|
||||
@property (nonatomic) XCTestExpectation *twoFingerDragExpectation;
|
||||
@property (assign) CGRect screenBounds;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MGLMapViewGestureRecognizerTests
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
|
||||
[MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
|
||||
NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
|
||||
self.screenBounds = UIScreen.mainScreen.bounds;
|
||||
self.mapView = [[MGLMapView alloc] initWithFrame:self.screenBounds styleURL:styleURL];
|
||||
self.mapView.zoomLevel = 16;
|
||||
self.mapView.delegate = self;
|
||||
|
||||
self.viewController = [[UIViewController alloc] init];
|
||||
self.viewController.view = [[UIView alloc] initWithFrame:self.screenBounds];
|
||||
[self.viewController.view addSubview:self.mapView];
|
||||
self.window = [[UIWindow alloc] initWithFrame:self.screenBounds];
|
||||
[self.window addSubview:self.viewController.view];
|
||||
[self.window makeKeyAndVisible];
|
||||
|
||||
if (!self.mapView.style) {
|
||||
_styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."];
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
|
||||
XCTAssertNotNil(mapView.style);
|
||||
XCTAssertEqual(mapView.style, style);
|
||||
|
||||
[_styleLoadingExpectation fulfill];
|
||||
}
|
||||
|
||||
- (void)testHandlePinchGestureContentInset {
|
||||
UIEdgeInsets contentInset = UIEdgeInsetsZero;
|
||||
self.mapView.contentInset = contentInset;
|
||||
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset);
|
||||
auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding.");
|
||||
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
contentInset = UIEdgeInsetsMake(20, 20, 20, 20);
|
||||
[self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil];
|
||||
XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertNotEqual(padding, cameraPadding);
|
||||
|
||||
UIPinchGestureRecognizerMock *pinchGesture = [[UIPinchGestureRecognizerMock alloc] initWithTarget:nil action:nil];
|
||||
pinchGesture.state = UIGestureRecognizerStateBegan;
|
||||
pinchGesture.scale = 1.0;
|
||||
[self.mapView handlePinchGesture:pinchGesture];
|
||||
XCTAssertNotEqual(padding, cameraPadding);
|
||||
|
||||
pinchGesture.state = UIGestureRecognizerStateChanged;
|
||||
[self.mapView handlePinchGesture:pinchGesture];
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match.");
|
||||
|
||||
pinchGesture.state = UIGestureRecognizerStateEnded;
|
||||
[self.mapView handlePinchGesture:pinchGesture];
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match.");
|
||||
|
||||
}
|
||||
|
||||
- (void)testHandleRotateGestureContentInset {
|
||||
UIEdgeInsets contentInset = UIEdgeInsetsZero;
|
||||
self.mapView.contentInset = contentInset;
|
||||
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset);
|
||||
auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding.");
|
||||
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
contentInset = UIEdgeInsetsMake(20, 20, 20, 20);
|
||||
[self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil];
|
||||
XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertNotEqual(padding, cameraPadding);
|
||||
|
||||
UIRotationGestureRecognizerMock *rotateGesture = [[UIRotationGestureRecognizerMock alloc] initWithTarget:nil action:nil];
|
||||
rotateGesture.state = UIGestureRecognizerStateBegan;
|
||||
rotateGesture.rotation = 1;
|
||||
[self.mapView handleRotateGesture:rotateGesture];
|
||||
XCTAssertNotEqual(padding, cameraPadding);
|
||||
|
||||
rotateGesture.state = UIGestureRecognizerStateChanged;
|
||||
[self.mapView handleRotateGesture:rotateGesture];
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match.");
|
||||
|
||||
rotateGesture.state = UIGestureRecognizerStateEnded;
|
||||
[self.mapView handleRotateGesture:rotateGesture];
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match.");
|
||||
|
||||
}
|
||||
|
||||
- (void)testHandleDoubleTapGestureContentInset {
|
||||
UIEdgeInsets contentInset = UIEdgeInsetsMake(1, 1, 1, 1);
|
||||
self.mapView.contentInset = contentInset;
|
||||
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset);
|
||||
auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding.");
|
||||
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
contentInset = UIEdgeInsetsMake(20, 20, 20, 20);
|
||||
[self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil];
|
||||
XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertNotEqual(padding, cameraPadding);
|
||||
|
||||
UITapGestureRecognizerMock *doubleTapGesture = [[UITapGestureRecognizerMock alloc] initWithTarget:nil action:nil];
|
||||
doubleTapGesture.mockTappedView = self.mapView;
|
||||
doubleTapGesture.mockTappedPoint = CGPointMake(1.0, 1.0);
|
||||
|
||||
[self.mapView handleDoubleTapGesture:doubleTapGesture];
|
||||
_doubleTapExpectation = [self expectationWithDescription:@"Double tap gesture animation."];
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[self->_doubleTapExpectation fulfill];
|
||||
});
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match.");
|
||||
|
||||
}
|
||||
|
||||
- (void)testHandleTwoFingerTapGesture {
|
||||
UIEdgeInsets contentInset = UIEdgeInsetsZero;
|
||||
self.mapView.contentInset = contentInset;
|
||||
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset);
|
||||
auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding.");
|
||||
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
contentInset = UIEdgeInsetsMake(20, 20, 20, 20);
|
||||
[self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil];
|
||||
XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertNotEqual(padding, cameraPadding);
|
||||
|
||||
UITapGestureRecognizerMock *twoFingerTap = [[UITapGestureRecognizerMock alloc] initWithTarget:nil action:nil];
|
||||
twoFingerTap.mockTappedView = self.mapView;
|
||||
twoFingerTap.mockTappedPoint = CGPointMake(1.0, 1.0);
|
||||
|
||||
[self.mapView handleTwoFingerTapGesture:twoFingerTap];
|
||||
_twoFingerExpectation = [self expectationWithDescription:@"Two Finger tap gesture animation."];
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[self->_twoFingerExpectation fulfill];
|
||||
});
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match.");
|
||||
}
|
||||
|
||||
- (void)testHandleQuickZoomGesture {
|
||||
UIEdgeInsets contentInset = UIEdgeInsetsZero;
|
||||
self.mapView.contentInset = contentInset;
|
||||
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset);
|
||||
auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding.");
|
||||
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
contentInset = UIEdgeInsetsMake(20, 20, 20, 20);
|
||||
[self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil];
|
||||
XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertNotEqual(padding, cameraPadding);
|
||||
|
||||
UILongPressGestureRecognizerMock *quickZoom = [[UILongPressGestureRecognizerMock alloc] initWithTarget:nil action:nil];
|
||||
quickZoom.state = UIGestureRecognizerStateBegan;
|
||||
[self.mapView handleQuickZoomGesture:quickZoom];
|
||||
XCTAssertNotEqual(padding, cameraPadding);
|
||||
|
||||
quickZoom.state = UIGestureRecognizerStateChanged;
|
||||
quickZoom.mockTappedPoint = CGPointMake(self.mapView.frame.size.width / 2, self.mapView.frame.size.height / 2);
|
||||
[self.mapView handleQuickZoomGesture:quickZoom];
|
||||
_quickZoomExpectation = [self expectationWithDescription:@"Quick zoom gesture animation."];
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[self->_quickZoomExpectation fulfill];
|
||||
});
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match.");
|
||||
|
||||
quickZoom.state = UIGestureRecognizerStateEnded;
|
||||
[self.mapView handleQuickZoomGesture:quickZoom];
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match.");
|
||||
}
|
||||
|
||||
- (void)testHandleTwoFingerDragGesture {
|
||||
UIEdgeInsets contentInset = UIEdgeInsetsZero;
|
||||
self.mapView.contentInset = contentInset;
|
||||
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset);
|
||||
auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding.");
|
||||
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
contentInset = UIEdgeInsetsMake(20, 20, 20, 20);
|
||||
[self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil];
|
||||
XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
|
||||
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertNotEqual(padding, cameraPadding);
|
||||
|
||||
UIPanGestureRecognizerMock *twoFingerDrag = [[UIPanGestureRecognizerMock alloc] initWithTarget:nil action:nil];
|
||||
twoFingerDrag.state = UIGestureRecognizerStateBegan;
|
||||
twoFingerDrag.firstFingerPoint = CGPointMake(self.mapView.frame.size.width / 3, self.mapView.frame.size.height/2);
|
||||
twoFingerDrag.secondFingerPoint = CGPointMake((self.mapView.frame.size.width / 2), self.mapView.frame.size.height/2);
|
||||
twoFingerDrag.numberOfTouches = 2;
|
||||
[self.mapView handleTwoFingerDragGesture:twoFingerDrag];
|
||||
XCTAssertNotEqual(padding, cameraPadding);
|
||||
|
||||
twoFingerDrag.state = UIGestureRecognizerStateChanged;
|
||||
twoFingerDrag.firstFingerPoint = CGPointMake(self.mapView.frame.size.width / 3, (self.mapView.frame.size.height/2)-10);
|
||||
twoFingerDrag.secondFingerPoint = CGPointMake((self.mapView.frame.size.width / 2), (self.mapView.frame.size.height/2)-10);
|
||||
[self.mapView handleTwoFingerDragGesture:twoFingerDrag];
|
||||
_twoFingerDragExpectation = [self expectationWithDescription:@"Quick zoom gesture animation."];
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[self->_twoFingerDragExpectation fulfill];
|
||||
});
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match.");
|
||||
|
||||
twoFingerDrag.state = UIGestureRecognizerStateEnded;
|
||||
[self.mapView handleTwoFingerDragGesture:twoFingerDrag];
|
||||
cameraPadding = self.mapView.mbglMap.getCameraOptions().padding;
|
||||
XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match.");
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -2,6 +2,7 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface MockUIPanGestureRecognizer : UIPanGestureRecognizer
|
||||
@property(nonatomic, readwrite) UIGestureRecognizerState state;
|
||||
@property NSUInteger mbx_numberOfFingersForGesture;
|
||||
@property CGPoint mbx_middlePoint;
|
||||
@property CGPoint mbx_westPoint;
|
||||
@@ -9,6 +10,9 @@
|
||||
@end
|
||||
|
||||
@implementation MockUIPanGestureRecognizer
|
||||
|
||||
@synthesize state;
|
||||
|
||||
- (instancetype)initWithTarget:(id)target action:(SEL)action {
|
||||
if (self = [super initWithTarget:target action:action]) {
|
||||
self.mbx_numberOfFingersForGesture = 2;
|
||||
|
||||
@@ -4,7 +4,26 @@
|
||||
@interface UIPinchGestureRecognizerMock : UIPinchGestureRecognizer
|
||||
@property (nonatomic, readwrite) CGFloat velocity;
|
||||
@property (nonatomic) CGPoint locationInViewOverride;
|
||||
@property(nonatomic, readwrite) UIGestureRecognizerState state;
|
||||
@end
|
||||
|
||||
@interface UIRotationGestureRecognizerMock : UIRotationGestureRecognizer
|
||||
@property(nonatomic, readwrite) UIGestureRecognizerState state;
|
||||
@end
|
||||
|
||||
@interface UITapGestureRecognizerMock : UITapGestureRecognizer
|
||||
@property (strong, nonatomic) UIView *mockTappedView;
|
||||
@property (assign) CGPoint mockTappedPoint;
|
||||
@end
|
||||
|
||||
@interface UILongPressGestureRecognizerMock : UILongPressGestureRecognizer
|
||||
@property(nonatomic, readwrite) UIGestureRecognizerState state;
|
||||
@property (assign) CGPoint mockTappedPoint;
|
||||
@end
|
||||
|
||||
@interface UIPanGestureRecognizerMock : UIPanGestureRecognizer
|
||||
@property(nonatomic, readwrite) UIGestureRecognizerState state;
|
||||
@property (assign) CGPoint firstFingerPoint;
|
||||
@property (assign) CGPoint secondFingerPoint;
|
||||
@property(nonatomic, readwrite) NSUInteger numberOfTouches;
|
||||
@end
|
||||
|
||||
@@ -1,11 +1,55 @@
|
||||
|
||||
#import "MGLMockGestureRecognizers.h"
|
||||
#import "objc/runtime.h"
|
||||
|
||||
@implementation UIPinchGestureRecognizerMock
|
||||
@synthesize velocity;
|
||||
@synthesize state;
|
||||
- (CGPoint)locationInView:(nullable UIView *)view { return self.locationInViewOverride; }
|
||||
@end
|
||||
|
||||
@implementation UIRotationGestureRecognizerMock
|
||||
- (CGPoint)locationInView:(nullable UIView*)view { return view.center; }
|
||||
@synthesize state;
|
||||
@end
|
||||
|
||||
@implementation UITapGestureRecognizerMock
|
||||
|
||||
+ (void)load {
|
||||
method_exchangeImplementations(class_getInstanceMethod(self, @selector(state)),
|
||||
class_getInstanceMethod(self, @selector(mockState)));
|
||||
}
|
||||
|
||||
- (UIGestureRecognizerState)mockState {
|
||||
return UIGestureRecognizerStateRecognized;
|
||||
}
|
||||
|
||||
- (UIView *)view {
|
||||
return self.mockTappedView;
|
||||
}
|
||||
|
||||
- (CGPoint)locationInView:(UIView *)view {
|
||||
return self.mockTappedPoint;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UILongPressGestureRecognizerMock
|
||||
@synthesize state;
|
||||
|
||||
- (CGPoint)locationInView:(UIView *)view {
|
||||
return self.mockTappedPoint;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation UIPanGestureRecognizerMock
|
||||
@synthesize state;
|
||||
@synthesize numberOfTouches;
|
||||
|
||||
- (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(UIView *)view {
|
||||
if (touchIndex) {
|
||||
return self.secondFingerPoint;
|
||||
}
|
||||
return self.firstFingerPoint;
|
||||
}
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user