热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

iOS-如何将MapView限制在特定区域?-iOS-HowtolimittheMapViewtoaspecificregion?

Ihavethefollowingproblem:我有以下问题:Ihaveadrawnmap(image)whichIaddtotheMapViewasan

I have the following problem:

我有以下问题:

I have a "drawn map" (image) which I add to the MapView as an Overlay. No Problem with that.. but I need to limit the MapView to the region of the Overlay, so a user isn't able to scroll/zoom outside of this region.. but it should be possible to scroll/zoom inside the "bounds" of the overlay - means I cannot just disable zoom/scrolling for the MapView.

我有一个“绘制的地图”(图像),我将它作为叠加添加到MapView中。这个模式没有任何的问题。但是我需要将MapView限制在覆盖区域,这样用户就不能在这个区域之外滚动/缩放。但是在覆盖层的“界限”内滚动/缩放应该是可能的——这意味着我不能仅为MapView禁用缩放/滚动。

Are there any ideas/solution on this topic? The reason for using the MapView/-Kit is that I need to add various POIs to the custom map. This may become more complex when just using an ImageView+ScrollView for presenting the custom map.

关于这个话题有什么想法/解决办法吗?使用MapView/-Kit的原因是我需要向自定义映射添加各种POIs。如果只是使用ImageView+ScrollView来表示定制映射,这可能会变得更加复杂。

I've researched alot on this topic, but I didn't found a nice solution.

关于这个话题我已经研究了很多,但是我没有找到一个好的解决方案。

Any help is appreciated!

任何帮助都是赞赏!

Best Regards, Christian

最好的祝福,基督教

Edit: This is our solution: You supply a topleft and a bottomright coordinate to limit the map. The (minimum) zoomlevel is also limited. I've deactivated decelerating and you are able to bounce a bit out of the map (for better performance/ux). I added a ~1km grey border to the overlay so the user isnÄt able to see the orignal worldmap of google.

编辑:这是我们的解决方案:您提供一个左上角和右下角的坐标来限制映射。zoomlevel也是有限的。我已经停用了减速,您可以从地图上反弹一点(为了更好的性能/用户体验)。我在覆盖层添加了一个~1km的灰色边框,这样用户就可以看到谷歌的原始世界地图了。

LimitedMapView.h:

LimitedMapView.h:

#import 
#import 


@interface LimitedMapView : MKMapView {

}

@property (nonatomic, assign) CLLocationCoordinate2D topLeftCoordinate;
@property (nonatomic, assign) CLLocationCoordinate2D bottomRightCoordinate;


@end

LimitedMapView.m:

LimitedMapView.m:

#import "LimitedMapView.h"

@implementation LimitedMapView

@synthesize topLeftCoordinate, bottomRightCoordinate;

- (void)scrollViewDidZoom:(UIScrollView *)scrollView{

    if([super respondsToSelector:@selector(scrollViewDidZoom:)]) [super scrollViewDidZoom:scrollView];

    if ([self region].span.latitudeDelta > 0.002401f || [self region].span.longitudeDelta > 0.003433f) {

        CLLocationCoordinate2D center = self.centerCoordinate;
        MKCoordinateSpan span = MKCoordinateSpanMake(0.002401f, 0.003433f);

        self.region = MKCoordinateRegionMake(center, span);

    }

}

-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{

    if([super respondsToSelector:@selector(scrollViewDidEndDragging:)]) [super scrollViewDidEndDragging:scrollView willDecelerate:decelerate];

    MKCoordinateRegion currentRegion = self.region;
    bool changeRegiOnLong= YES;
    bool changeRegiOnLat= YES;

    // LONGITUDE    
    if((currentRegion.center.longitude - (currentRegion.span.longitudeDelta/2))  self.bottomRightCoordinate.longitude) {

        currentRegion.center.lOngitude= (bottomRightCoordinate.longitude - (currentRegion.span.longitudeDelta/2));

    } else {

        changeRegiOnLong= NO;

    }

    // LATITUDE    
    if((currentRegion.center.latitude + (currentRegion.span.latitudeDelta/2)) > self.topLeftCoordinate.latitude) {

        currentRegion.center.latitude = (topLeftCoordinate.latitude - (currentRegion.span.latitudeDelta/2));

    } else if((currentRegion.center.latitude - (currentRegion.span.latitudeDelta/2)) 

3 个解决方案

#1


6  

By implementing :

通过实现:

-(void) mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated

-(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)动画

You should be able to reset region to your specific one.

您应该能够将区域重置为特定的区域。

Look at that answer to have an example of how to do this.

看看这个答案,并给出一个例子。


Another solution, that brings more precise events but is more complex (I'm currently using this successfully for another need) is to subclass MKMapView and override UIScrollViewDelegate protocol.

另一种解决方案是子类化MKMapView并覆盖UIScrollViewDelegate协议,它带来了更精确的事件,但更复杂(我目前在另一种需要中成功地使用了它)。

If you do that, make sure to call super implementation like that :

如果您这样做,请确保像这样调用super实现:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
  if ([super respondsToSelector:@selector(scrollViewWillBeginDragging:)])
    [super scrollViewWillBeginDragging:scrollView];
  // do what you want
}

Note: While the protocol is public, MKMapView implementation is unknown and might differ with iOS versions, so it is more safe to check with respondsToSelector: before. You must call super implementations or Map will just not work properly.

注意:虽然协议是公共的,但是MKMapView实现是未知的,并且可能与iOS版本不同,所以使用respondsToSelector: before检查更安全。您必须调用超级实现,否则映射将无法正常工作。

#2


13  

After trying different ways of limited MKMapView I've concluded that using mapDidChange, and resetting if you're center point goes outside of the boundaries works best, with animated: YES

在尝试了有限的MKMapView的不同方法之后,我得出结论,使用mapDidChange和重置如果你是中心点,那么在边界之外使用动画效果最好:是的

Here's how I do it (Using the New Zealand lat/Long span/center).

我是这样做的(使用新西兰的lat/Long span/center)。

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{ 
  if ((mapView.region.span.latitudeDelta > 15.589921 ) || (mapView.region.span.longitudeDelta > 175.836914) ) {
    CLLocationCoordinate2D centerCoord = CLLocationCoordinate2DMake(-41.162114, 172.836914);

    MKCoordinateSpan spanOfNZ = MKCoordinateSpanMake(13.589921, 14.062500 );

    MKCoordinateRegion NZRegion = MKCoordinateRegionMake(centerCoord, spanOfNZ);

    [mapView setRegion: NZRegion animated: YES];
  }

 if (abs(abs(mapView.region.center.latitude) - 41.162114) > (13.589921 / 2) ) {
    CLLocationCoordinate2D centerCoord = CLLocationCoordinate2DMake(-41.162114, 172.836914);

    MKCoordinateSpan spanOfNZ = MKCoordinateSpanMake(13.589921, 14.062500 );

    MKCoordinateRegion NZRegion = MKCoordinateRegionMake(centerCoord, spanOfNZ);

    [mapView setRegion: NZRegion animated: YES];

  }

  if (abs(abs(mapView.region.center.longitude) - 172.836914) > (14.062500 / 2) ) {
    CLLocationCoordinate2D centerCoord = CLLocationCoordinate2DMake(-41.162114, 172.836914);

     MKCoordinateSpan  spanOfNZ = MKCoordinateSpanMake(13.589921, 14.062500 );

     MKCoordinateRegion NZRegion = MKCoordinateRegionMake(centerCoord, spanOfNZ);

     [mapView setRegion: NZRegion animated: YES];
  }
}

#3


0  

I know this is a pretty old question, but to avoid the infinite loop you could try something like this: https://stackoverflow.com/a/4126011/1234011

我知道这是一个很老的问题,但是为了避免无限循环,您可以尝试以下方法:https://stackoverflow.com/a/4126011/1234011

Basically set a flag to prevent the callback from firing again if it was you who set the value.

基本上设置一个标志,如果设置值的是您,则防止回调再次触发。

  • Ken

推荐阅读
author-avatar
只喝大瓶的雪碧
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有