如何防止从无限水平滚动'GMSMapView'? [英] How do I prevent 'GMSMapView' from Infinite horizontal scrolling?

查看:180
本文介绍了如何防止从无限水平滚动'GMSMapView'?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何防止IOS 7上的'GMSMapView'无限水平滚动?我正在使用'MKTileOverlay'和'kGMSTypeNone'来显示延伸到世界各地的自定义图像。



(当用户向左滚动时,图像再次被重复,我希望滚动停止在这里。)

解决方案

嗯,我最初的想法是使用委托方法
$ b

- (void) mapView:(GMSMapView *)mapView willMove:(BOOL)gesture;



在达到滚动限制时移动相机。使用此功能,当用户滚动到最后时,您的地图视图可能会暂时超出您的限制(取决于委托方法调用的频率),但会动画回到所需限制。



如果您认为这种方法适合您,我们可以详细介绍。 更新:



好的,其实我意识到你应该使用另一个委托方法:

 <$ (GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position {



<而不是因为它在移动时给你不断的位置更新。在移动之前 willMove 只会被调用一次。无论如何,这个想法是你设置你的地图视图和限制(边界框),这将是你的覆盖的e / g框。我刚刚在我的位置附近创建了一个区域作为示例,并在其中定位了初始相机位置。这被设置在 viewDidLoad 方法中。


此外,在 didChangeCameraPosition 方法中,您


  1. 重新定位标记位置,以便您可以看到您当前指向的位置

  2. 检查您是否已经通过纬度/长度限制,这意味着您已经通过了叠加的边界并移动/返回动画

请注意,下面的代码不会检查您是否已通过角落同时),那么你可能会结束限制,但你可以很容易地检查更多的情况。

使用mapview设置和委托方法的Viewcontroller位于下方,我已经在此处上传完整的项目: https://www.dropbox.com/s/1a599wowvkumaa8/LimitingMap.tar.gz 。请不要忘记为您在应用委托中提供API密钥,因为我已将其从代码中移除。



因此,视图控制器如下:

  #importViewController.h
#import< GoogleMaps / GoogleMaps.h>

@interface ViewController()< GMSMapViewDelegate> {
CLLocationCoordinate2D center,topLeft,topRight,bottomLeft,bottomRight;
double leftLong,rightLong,bottomLat,topLat;
GMSMarker * currentPosition;
}

@property(弱,非原子)IBOutlet GMSMapView * mapView;

@end

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];

// GMSMapview本身连接在storyboard中,只需设置委托
self.mapView.delegate = self;

//纬度/长时间限制(边界框)
leftLong = 15.0;
rightLong = 16.0;
bottomLat = 45.0;
topLat = 46.0;

//地图视图的中心坐标,并将其设置为mapview
center = CLLocationCoordinate2DMake(45.895064,15.858220);
GMSCameraPosition * cameraPosition = [GMSCameraPosition cameraWithLatitude:center.latitude
longitude:center.longitude
zoom:10];
self.mapView.camera = cameraPosition;

//当前位置,用于显示标记
currentPosition = [GMSMarker markerWithPosition:center];
currentPosition.map = self.mapView;

//根据绘制为多段线的边界框的坐标限制的坐标
topLeft = CLLocationCoordinate2DMake(topLat,leftLong);
topRight = CLLocationCoordinate2DMake(topLat,rightLong);
bottomLeft = CLLocationCoordinate2DMake(bottomLat,leftLong);
bottomRight = CLLocationCoordinate2DMake(bottomLat,rightLong);


//用胖折线创建可视边界框
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;


$ b $ - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
//处理任何可以重新创建的资源。

$ b #pragma mark - Google Maps iOS SDK委托方法
$ b - (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position {


//将viewDidLoad中引入的GMSMarker重新定位到更新位置
currentPosition.position = position.target;

//有趣的部分 - 检测通过哪个限制的非优雅方式
//如果传递每个经纬度限制,地图将移动或动画到限制位置

if(position.target.latitude> topLat){//如果滚动经过上纬度
//在上纬度和当前经度(和缩放)处创建新的campera位置
GMSCameraPosition * goBackCamera = [GMSCameraPosition cameraWithLatitude:topLat
longitude:position.target.longitude
zoom:position.zoom];
//现在,您可以不使用动画,
//self.mapView.camera = goBackCamera;

//或者用动画,如你所见。
[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 GMSCameraPosition * goBackCamera = [GMSCameraPosition cameraWithLatitude:position.target.latitude
longitude:leftLong
zoom:position.zoom];
//self.mapView.camera = goBackCamera;
[self.mapView animateToCameraPosition:goBackCamera];
}


}

@end


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.

UPDATE:

OK, actually I realised you should use another delegate method:

- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position {

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.

Further, in didChangeCameraPosition method you

  1. reposition the marker position so you can see where you're currently pointing
  2. check if you've passed lat/long limits meaning you've passed bounds of your overlay and move/animate back

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.

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'?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆