问题描述
如何防止 IOS 7 上的GMSMapView"无限水平滚动?我正在使用MKTileOverlay"和kGMSTypeNone"来显示一个遍布世界各地的自定义图像.
How do I prevent 'GMSMapView' on IOS 7 from Infinite horizontal scrolling? I am using a 'MKTileOverlay' and 'kGMSTypeNone' to show a custom image which stretches all over the world.
(当用户向左滚动时,图像再次重复.我希望滚动停止在这里.)
(When the user scrolls to the left the image is repeated again. I would like the scrolling to stop here.)
推荐答案
嗯,我最初的想法是使用委托方法
Hmm, my initial idea would be to use delegate method
- (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture;
在达到滚动限制时将相机移回.使用此功能,当用户滚动到最后时,您的地图视图可能会暂时超出您的限制(取决于委托方法调用的频率),但会以动画方式返回到您想要的限制.
to move the camera back when your scrolling limit is reached. Using this, your map view may overshoot your limit temporarily (depending on the frequency of delegate method call) when user scrolls to the end, but will animate back to your desired limit.
如果您认为这种方法适合您,我们可以进一步详细说明.
We can go into further details if you think this approach suits you.
更新:
好吧,实际上我意识到你应该使用另一种委托方法:
OK, actually I realised you should use another delegate method:
- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position {
相反,它会在移动时为您提供持续的位置更新.willMove
在移动前只调用一次.无论如何,这个想法是您设置地图视图和限制(边界框),这将是您的叠加层的 e/g 框.我刚刚在我的位置周围创建了一个区域作为示例,并将初始相机位置定位在其中.这是在 viewDidLoad
方法中设置的.
instead as it gives you constant position updates when moving. willMove
is called only once before moving. Anyway, the idea is that you set up your map view and limits (bounding box), that would be e/g box of your overlay. I've just created an area around my location as an example and positioned initial camera position inside it. That's set up in viewDidLoad
method.
此外,在 didChangeCameraPosition
方法中你
- 重新定位标记位置,以便您可以看到当前指向的位置
- 检查您是否已通过纬度/经度限制,这意味着您已通过叠加层的边界并移动/动画返回
请注意,下面的代码不会检查您是否已经通过了一个角落(同时经纬度和经度限制),那么您最终可能会超出限制,但您可以使用更多 if 轻松检查该条件.
Mind that the code below doesn't check if you've passed through a corner (lat and long limit simultaneously), then you might end up off limits, but you can easily check for that condition with more if's.
带有地图视图设置和委托方法的视图控制器如下,我已经在这里上传了完整的项目:https://www.dropbox.com/s/1a599wowvkumaa8/LimitingMap.tar.gz.请不要忘记在应用委托中为您提供 API 密钥,因为我已从代码中删除了我的 API 密钥.
Viewcontroller with mapview setup and delegate methods is below, and I've uploaded the complete project here: https://www.dropbox.com/s/1a599wowvkumaa8/LimitingMap.tar.gz . Please, don't forget to provide you API key in app delegate as I've removed mine from the code.
所以,视图控制器如下:
So, the view controller is as follows:
#import "ViewController.h"
#import <GoogleMaps/GoogleMaps.h>
@interface ViewController () <GMSMapViewDelegate> {
CLLocationCoordinate2D center, topLeft, topRight, bottomLeft, bottomRight;
double leftLong, rightLong, bottomLat, topLat;
GMSMarker *currentPosition;
}
@property (weak, nonatomic) IBOutlet GMSMapView *mapView;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// GMSMapview itself is wired in storyboard, just set delegate
self.mapView.delegate = self;
// Lat/long limits (bounding box)
leftLong = 15.0;
rightLong = 16.0;
bottomLat = 45.0;
topLat = 46.0;
// center coordinate for map view and set it to mapview
center = CLLocationCoordinate2DMake(45.895064, 15.858220);
GMSCameraPosition *cameraPosition = [GMSCameraPosition cameraWithLatitude:center.latitude
longitude:center.longitude
zoom:10];
self.mapView.camera = cameraPosition;
// Current position, for displaying marker
currentPosition = [GMSMarker markerWithPosition:center];
currentPosition.map = self.mapView;
// coordinates based on coordinate limits for bounding box drawn as polyline
topLeft = CLLocationCoordinate2DMake(topLat, leftLong);
topRight = CLLocationCoordinate2DMake(topLat, rightLong);
bottomLeft = CLLocationCoordinate2DMake(bottomLat, leftLong);
bottomRight = CLLocationCoordinate2DMake(bottomLat, rightLong);
// Create visual bounding box with fat polyline
GMSMutablePath *path = [[GMSMutablePath alloc] init];
[path addCoordinate:topLeft];
[path addCoordinate:topRight];
[path addCoordinate:bottomRight];
[path addCoordinate:bottomLeft];
[path addCoordinate:topLeft];
GMSPolyline *polyLine = [GMSPolyline polylineWithPath:path];
polyLine.strokeWidth = 10.0;
polyLine.map = self.mapView;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Google Maps iOS SDK delegate methods
- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position {
// Reposition GMSMarker introduced in viewDidLoad to updated position
currentPosition.position = position.target;
// The interesting part - a non-elegant way to detect which limit was passed
// If each of lat/long limits is passed, map will move or animate to limiting position
if (position.target.latitude > topLat) { // If you scroll past upper latitude
// Create new campera position AT upper latitude and current longitude (and zoom)
GMSCameraPosition *goBackCamera = [GMSCameraPosition cameraWithLatitude:topLat
longitude:position.target.longitude
zoom:position.zoom];
// Now, you can go back without animation,
//self.mapView.camera = goBackCamera;
// or with animation, as you see fit.
[self.mapView animateToCameraPosition:goBackCamera];
}
if (position.target.latitude < bottomLat) {
GMSCameraPosition *goBackCamera = [GMSCameraPosition cameraWithLatitude:bottomLat
longitude:position.target.longitude
zoom:position.zoom];
//self.mapView.camera = goBackCamera;
[self.mapView animateToCameraPosition:goBackCamera];
}
if (position.target.longitude > rightLong) {
GMSCameraPosition *goBackCamera = [GMSCameraPosition cameraWithLatitude:position.target.latitude
longitude:rightLong
zoom:position.zoom];
//self.mapView.camera = goBackCamera;
[self.mapView animateToCameraPosition:goBackCamera];
}
if (position.target.longitude < leftLong) {
GMSCameraPosition *goBackCamera = [GMSCameraPosition cameraWithLatitude:position.target.latitude
longitude:leftLong
zoom:position.zoom];
//self.mapView.camera = goBackCamera;
[self.mapView animateToCameraPosition:goBackCamera];
}
}
@end
这篇关于如何防止“GMSMapView"无限水平滚动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!