Skip to content
This repository has been archived by the owner on Jun 21, 2023. It is now read-only.

[ios]Add a maximumWidthRatio property to customize maximum width of scale bar. #65

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions platform/ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started.

## Master

* Added `MGLMapView.maximumWidthRatio` property for customizing the width ratio of map view's scale bar. ([#65](https://github.com/mapbox/mapbox-gl-native-ios/pull/65))

## 5.7.0 - February 13, 2020

### Bug fixes
Expand Down
7 changes: 7 additions & 0 deletions platform/ios/src/MGLMapView.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,13 @@ MGL_EXPORT
*/
@property (nonatomic, assign) CGPoint scaleBarMargins;

/**
The maximum width ratio of the scale bar relative to the map view's frame.
m-stephen marked this conversation as resolved.
Show resolved Hide resolved
This value is limited from 0.1 to 1.
Default is 0.5(half of map view's width).
*/
@property (nonatomic, assign) CGFloat scaleBarMaximumWidthRatio;
m-stephen marked this conversation as resolved.
Show resolved Hide resolved

/**
A control indicating the map’s direction and allowing the user to manipulate
the direction, positioned in the upper-right corner.
Expand Down
15 changes: 15 additions & 0 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ - (void)commonInit
_scaleBarConstraints = [NSMutableArray array];
_scaleBarPosition = MGLOrnamentPositionTopLeft;
_scaleBarMargins = MGLOrnamentDefaultPositionOffset;
_scaleBar.margins = MGLOrnamentDefaultPositionOffset;

[self installConstraints];

Expand Down Expand Up @@ -806,9 +807,22 @@ - (void)setScaleBarPosition:(MGLOrnamentPosition)scaleBarPosition {
- (void)setScaleBarMargins:(CGPoint)scaleBarMargins {
MGLLogDebug(@"Setting scaleBarMargins: (x:%f, y:%f)", scaleBarMargins.x, scaleBarMargins.y);
_scaleBarMargins = scaleBarMargins;
if([self.scaleBar isKindOfClass:[MGLScaleBar class]]) {
((MGLScaleBar *)self.scaleBar).margins = scaleBarMargins;
}
[self installScaleBarConstraints];
}

- (void)setScaleBarMaximumWidthRatio:(CGFloat)scaleBarMaximumWidthRatio {
m-stephen marked this conversation as resolved.
Show resolved Hide resolved
m-stephen marked this conversation as resolved.
Show resolved Hide resolved
MGLLogDebug(@"Setting scale bar maximum width ratio: %f", scaleBarMaximumWidthRatio);
_scaleBarMaximumWidthRatio = scaleBarMaximumWidthRatio;
if([self.scaleBar isKindOfClass:[MGLScaleBar class]]) {
((MGLScaleBar *)self.scaleBar).maximumWidthRatio = scaleBarMaximumWidthRatio;
[(MGLScaleBar *)self.scaleBar setNeedsRecalculateSize];
}
[self updateScaleBar];
}

- (void)setCompassViewPosition:(MGLOrnamentPosition)compassViewPosition {
MGLLogDebug(@"Setting compassViewPosition: %lu", compassViewPosition);
_compassViewPosition = compassViewPosition;
Expand Down Expand Up @@ -1004,6 +1018,7 @@ - (void)layoutSubviews
// `_mbglMap->setSize()` just below that triggers rendering update which triggers
// another scale bar update which causes a rendering update loop and a major performace
// degradation.
[(MGLScaleBar *)self.scaleBar setNeedsRecalculateSize];
[self.scaleBar invalidateIntrinsicContentSize];

[self adjustContentInset];
Expand Down
11 changes: 11 additions & 0 deletions platform/ios/src/MGLScaleBar.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,15 @@
// Sets the scale and redraws the scale bar
@property (nonatomic, assign) CLLocationDistance metersPerPoint;

/*
The maximum width ratio of the scale bar relative to the map view's frame.
This value is limited from 0.1 to 1.
Default is 0.5(half of map view's width).
*/
@property (nonatomic, assign) CGFloat maximumWidthRatio;

@property (nonatomic, assign) CGPoint margins;

- (void)setNeedsRecalculateSize;

@end
27 changes: 26 additions & 1 deletion platform/ios/src/MGLScaleBar.mm
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ - (instancetype)initWithFrame:(CGRect)frame {

- (void)commonInit {
_size = CGSizeZero;
_maximumWidthRatio = 0.5;

_primaryColor = [UIColor colorWithRed:18.0/255.0 green:45.0/255.0 blue:17.0/255.0 alpha:1];
_secondaryColor = [UIColor colorWithRed:247.0/255.0 green:247.0/255.0 blue:247.0/255.0 alpha:1];
Expand Down Expand Up @@ -229,7 +230,25 @@ - (CGFloat)actualWidth {
- (CGFloat)maximumWidth {
// TODO: Consider taking Scale Bar margins into account here.
CGFloat fullWidth = CGRectGetWidth(self.superview.bounds);
return floorf(fullWidth / 2);

if(self.maximumWidthRatio < 0.1) {
self.maximumWidthRatio = 0.1;
}
else if (self.maximumWidthRatio > 1) {
self.maximumWidthRatio = 1;
}

CGFloat result = floorf(fullWidth * self.maximumWidthRatio);
return result > fullWidth - (self.margins.x * 2) ? fullWidth - (self.margins.x * 2) : result;
}

- (void)setMaximumWidthRatio:(CGFloat)maximumWidthRatio {
_maximumWidthRatio = maximumWidthRatio;

[self updateVisibility];

self.recalculateSize = YES;
[self invalidateIntrinsicContentSize];
}

- (CGFloat)unitsPerPoint {
Expand Down Expand Up @@ -297,6 +316,12 @@ - (void)setMetersPerPoint:(CLLocationDistance)metersPerPoint {
[self invalidateIntrinsicContentSize];
}

- (void)setNeedsRecalculateSize {
self.recalculateSize = YES;
[self setNeedsUpdateConstraints];
[self updateConstraintsIfNeeded];
}

- (CGSize)intrinsicContentSize {
// Size is calculated elsewhere - since intrinsicContentSize is part of the
// constraint system, this should be done in updateConstraints
Expand Down
38 changes: 36 additions & 2 deletions platform/ios/test/MGLMapViewScaleBarTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ - (void)testDirectlySettingScaleBarViewHiddenProperty {
// ... but triggering any camera event will update it.
self.mapView.zoomLevel = 1;
[self.mapView layoutIfNeeded];

XCTAssertTrue(CGSizeEqualToSize(scaleBar.intrinsicContentSize, CGSizeZero));
XCTAssertEqual(scaleBar.alpha, 0);

Expand All @@ -67,4 +67,38 @@ - (void)testDirectlySettingScaleBarViewHiddenProperty {

XCTAssertGreaterThan(scaleBar.alpha, 0);
XCTAssertFalse(CGSizeEqualToSize(scaleBar.intrinsicContentSize, CGSizeZero));
}@end
}

- (void)testScaleBarSizeChanged {

// The bar maximum bar width can only limit the bar's total width.
// Sometimes we should include some space for last label width, the maximum last label width is 30.
// We add this hint value to avoid testing failed when need a extra space for last label.
CGFloat scaleBarLastLabelWidthHint = 30.0f;

self.mapView.scaleBarMaximumWidthRatio = 0.5;
UIView *scaleBar = self.mapView.scaleBar;
scaleBar.hidden = NO;

self.mapView.zoomLevel = 15;
[self.mapView layoutIfNeeded];

XCTAssertLessThanOrEqual(scaleBar.intrinsicContentSize.width, self.mapView.frame.size.width/2 + scaleBarLastLabelWidthHint);

self.mapView.zoomLevel = 10;
[self.mapView layoutIfNeeded];
XCTAssertLessThanOrEqual(scaleBar.intrinsicContentSize.width, self.mapView.frame.size.width/2 + scaleBarLastLabelWidthHint);

CGRect frame = self.mapView.frame;
frame.size = CGSizeMake(frame.size.width/2, frame.size.height);
self.mapView.frame = frame;
[self.mapView layoutIfNeeded];

XCTAssertLessThanOrEqual(scaleBar.intrinsicContentSize.width, self.mapView.frame.size.width/2 + scaleBarLastLabelWidthHint);

self.mapView.scaleBarMaximumWidthRatio = 0.3;

XCTAssertLessThanOrEqual(scaleBar.intrinsicContentSize.width, self.mapView.frame.size.width * 0.3 + scaleBarLastLabelWidthHint);
}

@end