Как предотвратить бесконечную горизонтальную прокрутку GMSMapView?

Как предотвратить «GMSMapView» на IOS 7 от бесконечной горизонтальной прокрутки? Я использую «MKTileOverlay» и «kGMSTypeNone», чтобы показать пользовательское изображение, которое растягивается по всему миру.

(Когда пользователь прокручивает влево, изображение повторяется снова. Я бы хотел, чтобы прокрутка остановилась здесь.)


person jack    schedule 17.01.2014    source источник


Ответы (2)


Хм, моя первоначальная идея состояла в том, чтобы использовать метод делегата

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

чтобы переместить камеру назад, когда ваш предел прокрутки достигнут. Используя это, ваше представление карты может временно превысить ваш предел (в зависимости от частоты вызова метода делегата), когда пользователь прокручивает до конца, но анимация вернется к желаемому пределу.

Мы можем углубиться в детали, если вы считаете, что этот подход вам подходит.

ОБНОВЛЕНИЕ:

Хорошо, на самом деле я понял, что вы должны использовать другой метод делегата:

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

вместо этого, поскольку он дает вам постоянные обновления положения при движении. willMove вызывается только один раз перед перемещением. В любом случае, идея состоит в том, что вы настраиваете свой вид карты и ограничения (граничную рамку), которая будет e/g рамкой вашего наложения. В качестве примера я только что создал область вокруг своего местоположения и разместил в ней начальную позицию камеры. Это настроено в методе viewDidLoad.

Далее в методе didChangeCameraPosition вы

  1. изменить положение маркера, чтобы вы могли видеть, куда вы сейчас указываете
  2. проверьте, прошли ли вы пределы широты / долготы, что означает, что вы прошли границы своего наложения, и переместите / анимируйте назад

Имейте в виду, что приведенный ниже код не проверяет, прошли ли вы через угол (широта и длина одновременно), тогда вы можете оказаться за пределами ограничений, но вы можете легко проверить это условие с помощью большего количества если.

Контроллер просмотра с настройкой карты и методами делегирования приведен ниже, и я загрузил полный проект здесь: https://www.dropbox.com/s/1a599wowvkumaa8/LimitingMap.tar.gz . Пожалуйста, не забудьте предоставить вам ключ API в делегате приложения, так как я удалил свой из кода.

Итак, контроллер представления выглядит следующим образом:

#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
person Vladimir Kolbas    schedule 18.01.2014
comment
да, было бы здорово, если бы вы могли предоставить более подробную информацию!. Я думаю, что это единственный способ дополнить свое собственное изображение большим толстым серым прямоугольником. это сделало бы перерегулирование не столь очевидным, потому что пользователь просто увидел бы часть серого заполнения.... - person jack; 18.01.2014
comment
Да, это, возможно, не самое элегантное решение, но оно работает, и вы можете улучшить его, если подход вам подходит. Повеселись :) - person Vladimir Kolbas; 19.01.2014

Ваш код не всегда работал, поэтому я улучшил его (также быстрая версия)

     func mapView(mapView: GMSMapView, didChangeCameraPosition position: GMSCameraPosition) {

        var latitude  = position.target.latitude;
        var longitude = position.target.longitude;

        if (position.target.latitude > bounds.northEast.latitude) {
            latitude = bounds.northEast.latitude;
        }

        if (position.target.latitude < bounds.southWest.latitude) {
            latitude = bounds.southWest.latitude;
        }

        if (position.target.longitude > bounds.northEast.longitude) {
            longitude = bounds.northEast.longitude;
        }

        if (position.target.longitude < bounds.southWest.longitude) {
            longitude = bounds.southWest.longitude;
        }

        if (latitude != position.target.latitude || longitude != position.target.longitude) {

            var l = CLLocationCoordinate2D();
            l.latitude  = latitude;
            l.longitude = longitude;

            mapView.animateToLocation(l);

        }
    } 
person noisedan    schedule 01.07.2016
comment
Это здорово и работает! (хотя последнее имя функции - func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) { ) Если кто-то придет сюда, задаваясь вопросом, почему в iOS нет готовой функции для этого - ее нет. Android SDK имеет setLatLngBoundsForCameraTarget, но чтобы сделать то же самое в iOS, используйте приведенный выше код. - person J.C; 16.03.2017