任何人都知道在 MKMapView 上实现边界的简单方法。例如,我想告诉地图它只能停留在一个区域。我希望用户能够滚动,但当他们到达某个纬度/经度时让他们停下来。我尝试使用 willChangeRegion: 委托,但这把我搞砸了。谢谢。
3 回答
我刚刚写了一篇关于这个的博客文章,在这里查看:http: //blog.jamgraham.com/blog/2012/04/29/adding-boundaries-to-mkmapview/
我参与了一个需要锁定 MKMapView 边界的项目。由于苹果没有提供开箱即用的解决方案,因此我们留下了 MKMapView 的子类。这非常简单,您可以访问地图中的 UIScrollView 和 MKMapView 中的其他有趣对象。
现在想看代码吗?它在这里可用:https ://github.com/jamgraham/geoFencer
锁定 MKMapView 的边界会调用两个一般步骤。首先是将缩放级别锁定为最小值和最大值。其次是防止用户滚动到您创建的代工厂之外。让我们通过查看我们需要覆盖的代表来了解这些
1.缩放级别
这很简单。目标是在用户缩放时检查缩放级别,并在用户停止缩放时再次检查。
-(void)scrollViewDidZoom:(UIScrollView *)scrollView;
-(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
2.滚动边界
这有点复杂。当用户在 UIScrollView 中滚动地图时,我们要确保他们不会超出边界,如果他们这样做,我们想要阻止它们。当我们看到用户离开边界时,我们可以通过将地图重新定位到边界来实现这一点。这种情况发生得足够快,用户感觉像是撞到了墙而不是地图在晃动。以下是我们需要注意的代表:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView;
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
3.复制粘贴
随意复制并粘贴下面的自定义 MKMapView。在显示地图的 UIViewController 中,自定义地图视图需要设置边界
视图控制器.m
//Set map boundaries
mapView.showsUserLocation = YES;
[mapViewsetZoomMax:0.015551];
[mapViewsetZoomMin: 0.346360];
mapView.top = 37.773498;
mapView.bottom = 37.745130;
mapView.left = -122.430365;
mapView.right = -122.401623;
GeoMapView.h
@interface GeoMapView : MKMapView
{
MKCoordinateRegion cordRegion;
CLLocationCoordinate2D oldcenter;
double left;
double right;
double top;
double bottom;
double zoomMax;
double zoomMin;
}
-(void)checkZoom;
-(void)checkScroll;
@property (nonatomic) double left;
@property (nonatomic) double right;
@property (nonatomic) double top;
@property (nonatomic) double bottom;
@property (nonatomic) double zoomMax;
@property (nonatomic) double zoomMin;
@end
GeoMapView.m
#import "GeoMapView.h"
@implementation GeoMapView
@synthesize left, right, top, bottom,zoomMax,zoomMin;
- (id)initWithFrame:(CGRect)frame
{
self = [superinitWithFrame:frame];
if (self) {
}
returnself;
}
-(void)scrollViewDidZoom:(UIScrollView *)scrollView {
[selfcheckZoom];
}
-(void)checkZoom{
UIScrollView * scroll = [[[[selfsubviews] objectAtIndex:0] subviews] objectAtIndex:0];
if (scroll.zoomScale < zoomMax) {
NSLog(@"Reached Max Zoom");
[scroll setZoomScale:zoomMaxanimated:NO];
}
if (scroll.zoomScale >= zoomMin) {
NSLog(@"Reached Min Zoom");
[scroll setZoomScale:zoomMinanimated:NO];
}
}
-(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
UIScrollView * scroll = [[[[selfsubviews] objectAtIndex:0] subviews] objectAtIndex:0];
if (scroll.zoomScale > zoomMin) {
[scroll setZoomScale:zoomMinanimated:NO];
}
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
[selfcheckScroll];
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
[selfcheckScroll];
}
-(void)checkScroll{
@try{
cordRegion = self.region;
CLLocationCoordinate2D center = self.region.center;
CLLocationCoordinate2D northWestCorner, southEastCorner;
northWestCorner.latitude = center.latitude + (self.region.span.latitudeDelta / 2.0);
northWestCorner.longitude = center.longitude - (self.region.span.longitudeDelta / 2.0);
southEastCorner.latitude = center.latitude - (self.region.span.latitudeDelta / 2.0);
southEastCorner.longitude = center.longitude + (self.region.span.longitudeDelta / 2.0);
CLLocationCoordinate2D newcenter;
newcenter.latitude = self.region.center.latitude;
newcenter.longitude = self.region.center.longitude;
//LEFT
CLLocationDegrees farLeft = left;
CLLocationDegrees snapToLeft = farLeft + (self.region.span.longitudeDelta / 2.0);
if (northWestCorner.longitude < farLeft)
{
newcenter.longitude = snapToLeft;
cordRegion = self.region;
}
//RIGHT
CLLocationDegrees r = (self.region.span.longitudeDelta / 2.0);
CLLocationDegrees farRight = right;
CLLocationDegrees snapToRight = farRight - r;
if (southEastCorner.longitude > farRight)
{
newcenter.longitude = snapToRight;
}
//TOP
CLLocationDegrees farTop = top;
CLLocationDegrees snapToTop = top - (self.region.span.latitudeDelta / 2.0);
if (northWestCorner.latitude > farTop)
{
newcenter.latitude = snapToTop;
}
//BOTTOM
CLLocationDegrees farBottom = bottom;
CLLocationDegrees rr = (self.region.span.latitudeDelta / 2.0);
CLLocationDegrees snapToBottom = bottom + rr;
if (southEastCorner.latitude < farBottom)
{
newcenter.latitude = snapToBottom;
}
[selfsetCenterCoordinate:newcenter animated:NO];
}
@catch (NSException *e) {
}
@finally {}
}
@end
想法
现在,地理围栏中有很多很酷的东西。一些想法:
- 输入地址并将地图锁定到该地址
- 带有地图叠加层的地理围栏
- 当用户实际访问这些物理位置时解锁地图区域的物理游戏。
所以我将继续回答我自己的问题,并说不,没有简单的方法来实现这种行为。您不仅要检查边界,还必须检查滚动的方向,控制台一直告诉我:滚动后的最后一次触摸,但没有调用 scrollViewDidEndDragging:willDecelerate:!我想我还有很多研究要做...
我一直在做一些研究,发现没有简单的方法可以做到这一点。
所以我的解决方案是将地图锁定在某个区域,并让包含 MKMapView 的 scrollView 进行放大和缩小。