我試圖將一個自定義圖像添加到MKMapView
作爲MKOverlayView
- 我需要限制用戶無法在覆蓋範圍外滾動。有沒有現有的功能來做到這一點?還是有其他建議?限制MKMapView滾動
謝謝,馬特
我試圖將一個自定義圖像添加到MKMapView
作爲MKOverlayView
- 我需要限制用戶無法在覆蓋範圍外滾動。有沒有現有的功能來做到這一點?還是有其他建議?限制MKMapView滾動
謝謝,馬特
如果你只想在覆蓋凍結地圖視圖,你可以在地圖視圖的區域設置爲疊加層的邊界,並設置scrollEnabled
和zoomEnabled
到NO
。
但是,這不會讓用戶滾動或縮放覆蓋的界限內。
有沒有內置的方式來限制地圖視圖覆蓋的界限,所以你必須手動做。首先,確保您的MKOverlay
對象實現boundingMapRect
屬性。然後可以在regionDidChangeAnimated
委託方法中根據需要手動調整視圖。
下面是一個如何做到這一點的例子。
下面的代碼應該在具有MKMapView
的類中。
確保地圖視圖最初設置爲覆蓋層可見的區域。
//add two ivars to the .h...
MKMapRect lastGoodMapRect;
BOOL manuallyChangingMapRect;
//in the .m...
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
if (manuallyChangingMapRect)
return;
lastGoodMapRect = mapView.visibleMapRect;
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
if (manuallyChangingMapRect) //prevents possible infinite recursion when we call setVisibleMapRect below
return;
// "theOverlay" below is a reference to your MKOverlay object.
// It could be an ivar or obtained from mapView.overlays array.
BOOL mapContainsOverlay = MKMapRectContainsRect(mapView.visibleMapRect, theOverlay.boundingMapRect);
if (mapContainsOverlay)
{
// The overlay is entirely inside the map view but adjust if user is zoomed out too much...
double widthRatio = theOverlay.boundingMapRect.size.width/mapView.visibleMapRect.size.width;
double heightRatio = theOverlay.boundingMapRect.size.height/mapView.visibleMapRect.size.height;
if ((widthRatio < 0.6) || (heightRatio < 0.6)) //adjust ratios as needed
{
manuallyChangingMapRect = YES;
[mapView setVisibleMapRect:theOverlay.boundingMapRect animated:YES];
manuallyChangingMapRect = NO;
}
}
else
if (![theOverlay intersectsMapRect:mapView.visibleMapRect])
{
// Overlay is no longer visible in the map view.
// Reset to last "good" map rect...
[mapView setVisibleMapRect:lastGoodMapRect animated:YES];
}
}
我試圖與內置MKCircle
疊加和似乎運作良好。
編輯:
,它工作的時間以及95%,但是,我已經通過一些測試,它可能在兩個位置之間振盪確認,然後進入一個無限循環。所以,我編輯了一點,我想這應該解決的問題:
// You can safely delete this method:
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
// prevents possible infinite recursion when we call setVisibleMapRect below
if (manuallyChangingMapRect) {
return;
}
// "theOverlay" below is a reference to your MKOverlay object.
// It could be an ivar or obtained from mapView.overlays array.
BOOL mapContainsOverlay = MKMapRectContainsRect(mapView.visibleMapRect, theOverlay.boundingMapRect);
if (mapContainsOverlay) {
// The overlay is entirely inside the map view but adjust if user is zoomed out too much...
double widthRatio = theOverlay.boundingMapRect.size.width/mapView.visibleMapRect.size.width;
double heightRatio = theOverlay.boundingMapRect.size.height/mapView.visibleMapRect.size.height;
// adjust ratios as needed
if ((widthRatio < 0.6) || (heightRatio < 0.6)) {
manuallyChangingMapRect = YES;
[mapView setVisibleMapRect:theOverlay.boundingMapRect animated:YES];
manuallyChangingMapRect = NO;
}
} else if (![theOverlay intersectsMapRect:mapView.visibleMapRect]) {
// Overlay is no longer visible in the map view.
// Reset to last "good" map rect...
manuallyChangingMapRect = YES;
[mapView setVisibleMapRect:lastGoodMapRect animated:YES];
manuallyChangingMapRect = NO;
} else {
lastGoodMapRect = mapView.visibleMapRect;
}
}
以防萬一有人在尋找一種快速MKOverlay
解決方案,這裏是一個:
- (void)viewDidLoad {
[super viewDidLoad];
MKCircle* circleOverlay = [MKCircle circleWithMapRect:istanbulRect];
[_mapView addOverlay:circleOverlay];
theOverlay = circleOverlay;
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay {
MKCircleView* circleOverlay = [[MKCircleView alloc] initWithCircle:overlay];
[circleOverlay setStrokeColor:[UIColor mainColor]];
[circleOverlay setLineWidth:4.f];
return circleOverlay;
}
在我的情況,我需要限制到具有左上角/右下角座標的平鋪疊加。以上代碼仍然運作良好,但取代theOverlay.boundingMapRect爲MKMapRect paddedBoundingMapRect
- (void)mapView:(MKMapView *)_mapView regionDidChangeAnimated:(BOOL)animated
{
if (manuallyChangingMapRect) //prevents possible infinite recursion when we call setVisibleMapRect below
return;
[self updateDynamicPaddedBounds];
MKMapPoint pt = MKMapPointForCoordinate(mapView.centerCoordinate);
BOOL mapInsidePaddedBoundingRect = MKMapRectContainsPoint(paddedBoundingMapRect,pt);
if (!mapInsidePaddedBoundingRect)
{
// Overlay is no longer visible in the map view.
// Reset to last "good" map rect...
manuallyChangingMapRect = YES;
[mapView setVisibleMapRect:lastGoodMapRect animated:YES];
manuallyChangingMapRect = NO;
}
-(void)updateDynamicPaddedBounds{
ENTER_METHOD;
CLLocationCoordinate2D northWestPoint= CLLocationCoordinate2DMake(-33.841171,151.237318);
CLLocationCoordinate2D southEastPoint= CLLocationCoordinate2DMake(-33.846127, 151.245058);
MKMapPoint upperLeft = MKMapPointForCoordinate(northWestPoint);
MKMapPoint lowerRight = MKMapPointForCoordinate(southEastPoint);
double width = lowerRight.x - upperLeft.x;
double height = lowerRight.y - upperLeft.y;
MKMapRect mRect = mapView.visibleMapRect;
MKMapPoint eastMapPoint = MKMapPointMake(MKMapRectGetMinX(mRect), MKMapRectGetMidY(mRect));
MKMapPoint westMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), MKMapRectGetMidY(mRect));
MKMapPoint northMapPoint = MKMapPointMake(MKMapRectGetMidX(mRect), MKMapRectGetMaxY(mRect));
MKMapPoint southMapPoint = MKMapPointMake(MKMapRectGetMidX(mRect), MKMapRectGetMinY(mRect));
double xMidDist = abs(eastMapPoint.x - westMapPoint.x)/2;
double yMidDist = abs(northMapPoint.y - southMapPoint.y)/2;
upperLeft.x = upperLeft.x + xMidDist;
upperLeft.y = upperLeft.y + yMidDist;
double paddedWidth = width - (xMidDist*2);
double paddedHeight = height - (yMidDist*2);
paddedBoundingMapRect= MKMapRectMake(upperLeft.x, upperLeft.y, paddedWidth, paddedHeight);
}
在夫特3.0安娜的(https://stackoverflow.com/a/4126011/3191130)溶液,我添加到延伸:
extension HomeViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
if manuallyChangingMapRect {
return
}
guard let overlay = self.mapOverlay else {
print("Overlay is nil")
return
}
guard let lastMapRect = self.lastGoodMapRect else {
print("LastGoodMapRect is nil")
return
}
let mapContainsOverlay = MKMapRectContainsRect(mapView.visibleMapRect, overlay.boundingMapRect)
if mapContainsOverlay {
let widthRatio: Double = overlay.boundingMapRect.size.width/mapView.visibleMapRect.size.width
let heightRatio: Double = overlay.boundingMapRect.size.height/mapView.visibleMapRect.size.height
// adjust ratios as needed
if (widthRatio < 0.9) || (heightRatio < 0.9) {
manuallyChangingMapRect = true
mapView.setVisibleMapRect(overlay.boundingMapRect, animated: true)
manuallyChangingMapRect = false
}
} else if !overlay.intersects(mapView.visibleMapRect) {
// Overlay is no longer visible in the map view.
// Reset to last "good" map rect...
manuallyChangingMapRect = true
mapView.setVisibleMapRect(lastMapRect, animated: true)
manuallyChangingMapRect = false
}
else {
lastGoodMapRect = mapView.visibleMapRect
}
}
}
要設置該地圖使用此:
override func viewDidLoad() {
super.viewDidLoad()
setupMap()
}
func setupMap() {
mapView.delegate = self
let radius:CLLocationDistance = 1000000
mapOverlay = MKCircle(center: getCenterCoord(), radius: radius)
if let mapOverlay = mapOverlay {
mapView.add(mapOverlay)
}
mapView.setRegion(MKCoordinateRegionMake(getCenterCoord(), getSpan()), animated: true)
lastGoodMapRect = mapView.visibleMapRect
}
func getCenterCoord() -> CLLocationCoordinate2D {
return CLLocationCoordinate2DMake(LAT, LON)
}
func getSpan() -> MKCoordinateSpan {
return MKCoordinateSpanMake(10, 10)
}
謝謝!那就是訣竅。 – mag725 2010-11-13 00:52:23
工作得很好。但不處理您在範圍之外平移(滑動,滾動,任意)的情況。 – horseshoe7 2011-07-20 19:07:08
@ horseshoe7,結束姿勢後,視圖是否會重新回到疊加層?此外,地圖必須在覆蓋層內部開始才能工作。如果您需要限制_while_用戶正在移動地圖,您可以使用UIPanGestureRecognizer並檢查手勢處理程序中的新地圖區域。 – Anna 2011-07-20 19:29:33