Ek açıklama pimlerine uyacak şekilde MKMapView yakınlaştırılıyor mu?


193

MKMapView kullanıyorum ve haritaya 5-10 kilometrelik bir alan hakkında bir dizi ek açıklama pimi ekledim. Uygulamayı çalıştırdığımda, haritam tüm dünyayı göstermek için uzaklaştırılmaya başlar, iğneler görüntüye sığacak şekilde haritayı yakınlaştırmanın en iyi yolu nedir?

EDIT: Benim ilk düşüncem MKCoordinateRegionMake kullanmak ve ek açıklamalarımdan koordinat merkezi, boylamDelta ve latitudeDelta hesaplamak olacaktır. Bunun işe yarayacağından eminim, ama sadece belirgin bir şey eksik olmadığımı kontrol etmek istedim.

Kod eklendi, BTW: FGLocation uygun bir sınıf MKAnnotation, locationFake NSMutableArraybu nesnelerden biridir. Yorumlar her zaman beklerim ....

- (MKCoordinateRegion)regionFromLocations {
    CLLocationCoordinate2D upper = [[locationFake objectAtIndex:0] coordinate];
    CLLocationCoordinate2D lower = [[locationFake objectAtIndex:0] coordinate];

    // FIND LIMITS
    for(FGLocation *eachLocation in locationFake) {
        if([eachLocation coordinate].latitude > upper.latitude) upper.latitude = [eachLocation coordinate].latitude;
        if([eachLocation coordinate].latitude < lower.latitude) lower.latitude = [eachLocation coordinate].latitude;
        if([eachLocation coordinate].longitude > upper.longitude) upper.longitude = [eachLocation coordinate].longitude;
        if([eachLocation coordinate].longitude < lower.longitude) lower.longitude = [eachLocation coordinate].longitude;
    }

    // FIND REGION
    MKCoordinateSpan locationSpan;
    locationSpan.latitudeDelta = upper.latitude - lower.latitude;
    locationSpan.longitudeDelta = upper.longitude - lower.longitude;
    CLLocationCoordinate2D locationCenter;
    locationCenter.latitude = (upper.latitude + lower.latitude) / 2;
    locationCenter.longitude = (upper.longitude + lower.longitude) / 2;

    MKCoordinateRegion region = MKCoordinateRegionMake(locationCenter, locationSpan);
    return region;
}

10
iOS 7 not: Yeni showAnnotations: animated: yöntemi, bu manuel bölge hesaplamasından kaçınmanıza yardımcı olabilir.

Yanıtlar:


123

Doğru anladınız.

Maksimum ve minimum enlem ve boylamlarınızı bulun, basit aritmetik uygulayın ve kullanın MKCoordinateRegionMake.

Kullanım, IOS 7 ve üzerinde showAnnotations:animated:, gelen MKMapView.h:

// Position the map such that the provided array of annotations are all visible to the fullest extent possible. 
- (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);

158
İOS 7 ve üstü için (Bakınız MKMapView.h): // Position the map such that the provided array of annotations are all visible to the fullest extent possible. - (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);
Abhishek Bedi

1
Bu iyi çalışır, ancak zaman zaman (harita) yakınlaştırmak (sonra bu yöntemi çağıran bir düğme kullanarak) ortalamak için çalıştığınızda çalışmıyor gibi görünüyor.
RPM

5
Bu showAnnotationskonum için bir ek açıklama mevcut olsa bile, ek açıklamaları haritaya eklediğini de belirtmek önemlidir .
Eneko Alonso

@EnekoAlonso removeAnnotations(_ annotations:)Hemen sonra arayarak bu sorunu çözebilirsinshowAnnotations(_ annotations:animated)
Alain Stulz

1
Ayrıca, showAnnotations, bölgeyi ek açıklama görüntüleyecek şekilde ayarlarken, bölgenin yine de en boy oranına uyacak şekilde ayarlandığı; ve bu bazı ek açıklamaları sıklıkla hariç tutar. Ayrıca showAnnotations'ın burada sunulan tek doğru çözüm olduğunu unutmayın; diğer cevapların hiçbiri uluslararası tarih çizgisini kapsayan ek açıklamaları ele almaya bile çalışmaz.
Gordon Dove

335

Burada bulduğum bu benim için çalıştı:

(DÜZENLEME: Rektifi sonsuz küçük olmayacağından emin olmak için pointRect'i 0,1 oranında artırmak için @ Micah'ın önerisini kullanarak çözümü güncelledim!)

MKMapRect zoomRect = MKMapRectNull;
for (id <MKAnnotation> annotation in mapView.annotations)
{
    MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
    MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
    zoomRect = MKMapRectUnion(zoomRect, pointRect);
}
[mapView setVisibleMapRect:zoomRect animated:YES];

 

Bunu, ilk satırı aşağıdaki ile değiştirerek userLocation pinini içerecek şekilde güncelleyebilirsiniz:

MKMapPoint annotationPoint = MKMapPointForCoordinate(mapView.userLocation.coordinate);
MKMapRect zoomRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);

4
Gerçekten güzel. Yine de isNull'ı kontrol etmenize gerek yok. MKMapRectUnion bunu sizin için yapar. Dokümanlardan: "Dikdörtgenlerden biri boşsa, bu yöntem diğer dikdörtgeni döndürür."
Felix Lamouroux

37
Çok güzel bir çözüm !!! İşte biraz dolgu eklemek için ekstra küçük bir dokunuş: double inset = -zoomRect.size.width * 0.1; [self.mapView setVisibleMapRect: MKMapRectInset (zoomRect, inset, inset) animasyonlu: YES];
Craig B

1
Müthiş! Potansiyel ekleme: 'geçerli konum ek açıklamasını' hariç tutmak istiyorsanız, for döngüsüne bir if ifadesi ekleyin: if (! [Ek açıklama isKindOfClass: [MKUserLocation class]])) {// Burada işleri yapın}
kgaidis

2
Dolgu için @CraigB çözümü mükemmel, ancak yol dikey olduğunda, örneğin güneyden kuzeye hareket gibi, bu kullanımı düzeltmek için iyi çalışmaz. yükseklik * 0.1);
Farhad Malekpour

1
Dolgu ile geliştirme: çift insetWidth = -zoomRect.size.width * 0.2; çift ​​insetHeight = -zoomRect.size.height * 0.2; MKMapRect insetRect = MKMapRectInset (zoomRect, insetWidth, insetHeight); Sonra bu yeni insertRect
dulgan

121

Apple, hayatı biraz basitleştirmek için IOS 7 için yeni bir yöntem ekledi.

[mapView showAnnotations:yourAnnotationArray animated:YES];

Harita görünümünde saklanan bir diziden kolayca çekebilirsiniz:

yourAnnotationArray = mapView.annotations;

ve kamerayı da hızlıca ayarlayın!

mapView.camera.altitude *= 1.4;

kullanıcı iOS 7+ veya OS X 10.9+ kurulu değilse bu çalışmaz. buradan özel animasyona göz atın


Bunun benim uygulamamdaki diğer bazı faktörlerden kaynaklanıp kaynaklanmadığından emin değilim, ancak showAnnotationsmanuel uygulamanın yaptığı gibi yakınlaştırma / ek açıklamaların yakın olmasını sağlamaz, bu yüzden manuel olanla sıkıştım.
Ted Avery

1
kameraların yüksekliğini mapView.camera.altitude * = .85 gibi bir kesirle çarpmayı deneyin; daha yakından görmek için
Ryan Berg

Bunu, geçerli görünür harita alanının dışındaki ek açıklamaları seçmek için de yararlı buldum. Varsayılan olarak, MapView görünür olmayan ek açıklamaları seçmez. SelectAnnotation'ı çağırmadan önce, görünür olmayan ek açıklamalarınızın bir dizisine sahip gösterileri çağırın ve harita görüntülenebilir alanını güncellemelidir.
MandisaW

42

Bu kodu kullanın ve benim için iyi çalışıyor:

-(void)zoomToFitMapAnnotations:(MKMapView*)aMapView
{
    if([aMapView.annotations count] == 0)
        return;

    CLLocationCoordinate2D topLeftCoord;
    topLeftCoord.latitude = -90;
    topLeftCoord.longitude = 180;

    CLLocationCoordinate2D bottomRightCoord;
    bottomRightCoord.latitude = 90;
    bottomRightCoord.longitude = -180;

    for(MapViewAnnotation *annotation in mapView.annotations)
    {
        topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
        topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);

        bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
        bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
    }

    MKCoordinateRegion region;
    region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
    region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
    region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; // Add a little extra space on the sides
    region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; // Add a little extra space on the sides

    region = [aMapView regionThatFits:region];
    [mapView setRegion:region animated:YES];
}

174,13666611126533: 46,969995730376894 - boylam: -109,2494943434474 ▿ 1: CLLocationCoordinate2D -: - enlem 63,23212154333072 boylam: - ▿ 2 elemanları ▿ 0: enlem CLLocationCoordinate2D için değil iş yap
Olexiy Pyvovarov

23

Swift kullanımda

mapView.showAnnotations(annotationArray, animated: true)

Hedef c

[mapView showAnnotations:annotationArray animated:YES];

2
Ek açıklamalar mapView üzerinde önceden ayarlanmışsa, bunlara doğrudan başvurabilirsiniz:mapView.showAnnotations(mapView.annotations, animated: true)
Justin Vallely

14

Cevabı Rafael Moreira'dan dönüştürdüm. Kredi ona gidiyor. Swift sürümünü arayanlar için kod:

 func zoomToFitMapAnnotations(aMapView: MKMapView) {
    guard aMapView.annotations.count > 0 else {
        return
    }
    var topLeftCoord: CLLocationCoordinate2D = CLLocationCoordinate2D()
    topLeftCoord.latitude = -90
    topLeftCoord.longitude = 180
    var bottomRightCoord: CLLocationCoordinate2D = CLLocationCoordinate2D()
    bottomRightCoord.latitude = 90
    bottomRightCoord.longitude = -180
    for annotation: MKAnnotation in myMap.annotations as! [MKAnnotation]{
        topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude)
        topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude)
        bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude)
        bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude)
    }

    var region: MKCoordinateRegion = MKCoordinateRegion()
    region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5
    region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5
    region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.4
    region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.4
    region = aMapView.regionThatFits(region)
    myMap.setRegion(region, animated: true)
}

14

Swift 3 Bu, haritadaki tüm ek açıklamaları sığdırmak için de doğru yoldur.

func zoomMapaFitAnnotations() {

        var zoomRect = MKMapRectNull
        for annotation in mapview.annotations {

            let annotationPoint = MKMapPointForCoordinate(annotation.coordinate)

            let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0)

            if (MKMapRectIsNull(zoomRect)) {
                zoomRect = pointRect
            } else {
                zoomRect = MKMapRectUnion(zoomRect, pointRect)
            }
        }
        self.mapview.setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(50, 50, 50, 50), animated: true)

    }

@ArshadShaik Swift 4.2 için yeni bir yanıt vermek istiyorsanız, çekinmeyin, ancak başka bir kullanıcının yayınına düzenleyerek cevap olarak eklemek için önerilen düzenlemeniz reddedildi.
Nick

13

@ jowie'nin çözümü harika çalışıyor. Bir yakalama, bir haritada yalnızca bir ek açıklama varsa, tamamen uzaklaştırılmış bir harita ile sonuçlanırsınız. SetVisibleMapRect'in yakınlaştırılacak bir şey olduğundan emin olmak için rect marka boyutuna 0,1 ekledim.

MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);

12

İOS 8 ve üstünü arıyorsanız , bunu yapmanın en basit yolu var layoutMargins: UIEdgeInsets { get set }aramadan önce harita görünümünüzü ayarlamaktırfunc showAnnotations(annotations: [MKAnnotation], animated: Bool)

Örneğin (Swift 2.1):

@IBOutlet weak var map: MKMapView! {
    didSet {
        map.delegate = self
        map.mapType = .Standard
        map.pitchEnabled = false
        map.rotateEnabled = false
        map.scrollEnabled = true
        map.zoomEnabled = true
    }
}

// call 'updateView()' when viewWillAppear or whenever you set the map annotations
func updateView() {
    map.layoutMargins = UIEdgeInsets(top: 25, left: 25, bottom: 25, right: 25)
    map.showAnnotations(map.annotations, animated: true)
}

12

Buradan ve buradan hızlı bir şekilde bazı kodları kullanarak tüm ek açıklamaları göstermek için bir uzantı oluşturdum. Bu, maksimum yakınlaştırma düzeyinde bile gösterilemezse tüm ek açıklamaları göstermez.

import MapKit

extension MKMapView {
    func fitAllAnnotations() {
        var zoomRect = MKMapRectNull;
        for annotation in annotations {
            let annotationPoint = MKMapPointForCoordinate(annotation.coordinate)
            let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
            zoomRect = MKMapRectUnion(zoomRect, pointRect);
        }
        setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50), animated: true)
    }
}

UIEdgeInsetsMakeParametreleri değiştirerek daha iyi sonuçlar elde etmeyi başardım , 30 ile 100 arasındaki değerler benim için iyi oldu. İPhone SE i) S 10.2 Simulator kullanarak test yapıyordum. Örnek kod: setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(100, 100, 100, 100), animated: true). Not olarak, Bu Kod Swift 3 ve XCode 8.2.1'de çalışır.
nyxee

8

Kullanıcıların konum iğnesini bu yöntemden hariç tutmak için for döngüsünde bu If döngüsü eklendi (benim durumumda ve belki de diğerlerinde gereklidir)

if (![annotation isKindOfClass:[MKUserLocation class]] ) {

//Code Here...

}

8

İOS 7 ve üstü için (Başvurmak MKMapView.h):

// Position the map such that the provided array of annotations are all visible to the fullest extent possible.          

- (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);

sözden - Abhishek Bedi

Sadece arayın:

 [yourMapView showAnnotations:@[yourAnnotation] animated:YES];

Sadece referans olarak, NS_AVAILABLE metni oradaydı çünkü Ocak 2011'de bir cihazda iOS 7'nin olması çok muhtemel değildi ve NS_AVAILABLE uygulamayı derleme hatası veya çökmesine karşı korudu.
Matthew Frederick

5

Swift'te

    var zoomRect = MKMapRectNull;

    for i in 0..<self.map.annotations.count {

        let annotation: MKAnnotation = self.map.annotations[i]

        let annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
        let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
        zoomRect = MKMapRectUnion(zoomRect, pointRect);
    }

    self.map.setVisibleMapRect(zoomRect, animated: true)

5
    var zoomRect: MKMapRect = MKMapRect.null
    for annotation in mapView.annotations {
        let annotationPoint = MKMapPoint(annotation.coordinate)
        let pointRect = MKMapRect(x: annotationPoint.x, y: annotationPoint.y, width: 0.1, height: 0.1)
        zoomRect = zoomRect.union(pointRect)
    }
    mapView.setVisibleMapRect(zoomRect, animated: true)

// Hızlı 5 için düzenlendi


4

Jowie sayesinde eski kategorimi daha şık bir çözüme güncelledim. Paylaşım tamamlandı, neredeyse kopyala ve yapıştır hazır çözüm

MKMapView + AnnotationsRegion.h

#import <MapKit/MapKit.h>

@interface MKMapView (AnnotationsRegion)

-(void)updateRegionForCurrentAnnotationsAnimated:(BOOL)animated;
-(void)updateRegionForCurrentAnnotationsAnimated:(BOOL)animated edgePadding:(UIEdgeInsets)edgePadding;

-(void)updateRegionForAnnotations:(NSArray *)annotations animated:(BOOL)animated;
-(void)updateRegionForAnnotations:(NSArray *)annotations animated:(BOOL)animated edgePadding:(UIEdgeInsets)edgePadding;

@end

MKMapView + AnnotationsRegion.m

#import "MKMapView+AnnotationsRegion.h"

@implementation MKMapView (AnnotationsRegion)

-(void)updateRegionForCurrentAnnotationsAnimated:(BOOL)animated{
    [self updateRegionForCurrentAnnotationsAnimated:animated edgePadding:UIEdgeInsetsZero];
}
-(void)updateRegionForCurrentAnnotationsAnimated:(BOOL)animated edgePadding:(UIEdgeInsets)edgePadding{
    [self updateRegionForAnnotations:self.annotations animated:animated edgePadding:edgePadding];
}

-(void)updateRegionForAnnotations:(NSArray *)annotations animated:(BOOL)animated{
    [self updateRegionForAnnotations:annotations animated:animated edgePadding:UIEdgeInsetsZero];
}
-(void)updateRegionForAnnotations:(NSArray *)annotations animated:(BOOL)animated edgePadding:(UIEdgeInsets)edgePadding{
    MKMapRect zoomRect = MKMapRectNull;
    for(id<MKAnnotation> annotation in annotations){
        MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
        MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
        zoomRect = MKMapRectUnion(zoomRect, pointRect);
    }
    [self setVisibleMapRect:zoomRect edgePadding:edgePadding animated:animated];
}

@end

Umarım birine yardımcı olur ve tekrar teşekkürler jowie!


4
 - (void)zoomMapViewToFitAnnotationsWithExtraZoomToAdjust:(double)extraZoom
{

    if ([self.annotations count] == 0) return;

   int i = 0;
  MKMapPoint points[[self.annotations count]];

   for (id<MKAnnotation> annotation in [self annotations])
  {
      points[i++] = MKMapPointForCoordinate(annotation.coordinate);
   }

  MKPolygon *poly = [MKPolygon polygonWithPoints:points count:i];

MKCoordinateRegion r = MKCoordinateRegionForMapRect([poly boundingMapRect]);
r.span.latitudeDelta += extraZoom;
r.span.longitudeDelta += extraZoom;

[self setRegion: r animated:YES];

}

4

Abhishek Bedi'nin bir yorumda belirttiği gibi, iOS7 için bunu yapmanın en iyi yolu şudur:

//from API docs: 
//- (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);
[self.mapView showAnnotations:self.mapView.annotations animated:YES];

Kişisel projem için (iOS7'den önce) çok yaygın bir işlem için "görünür alan" işlevini kapsüllemek üzere MKMapView sınıfına bir kategori ekledim: MKMapView örneğindeki şu anda yüklü tüm ek açıklamaları görebilecek şekilde ayarlama ( bu, yerleştirebildiğiniz kadar iğne ve kullanıcının konumunu içerir). sonuç şuydu:

.h dosyası

#import <MapKit/MapKit.h>

@interface MKMapView (Extensions)

-(void)ij_setVisibleRectToFitAllLoadedAnnotationsAnimated:(BOOL)animated;
-(void)ij_setVisibleRectToFitAnnotations:(NSArray *)annotations animated:(BOOL)animated;


@end

.m dosyası

#import "MKMapView+Extensions.h"

@implementation MKMapView (Extensions)

/**
 *  Changes the currently visible portion of the map to a region that best fits all the currently loadded annotations on the map, and it optionally animates the change.
 *
 *  @param animated is the change should be perfomed with an animation.
 */
-(void)ij_setVisibleRectToFitAllLoadedAnnotationsAnimated:(BOOL)animated
{
    MKMapView * mapView = self;

    NSArray * annotations = mapView.annotations;

    [self ij_setVisibleRectToFitAnnotations:annotations animated:animated];

}


/**
 *  Changes the currently visible portion of the map to a region that best fits the provided annotations array, and it optionally animates the change.
    All elements from the array must conform to the <MKAnnotation> protocol in order to fetch the coordinates to compute the visible region of the map.
 *
 *  @param annotations an array of elements conforming to the <MKAnnotation> protocol, holding the locations for which the visible portion of the map will be set.
 *  @param animated    wether or not the change should be perfomed with an animation.
 */
-(void)ij_setVisibleRectToFitAnnotations:(NSArray *)annotations animated:(BOOL)animated
{
    MKMapView * mapView = self;

    MKMapRect r = MKMapRectNull;
    for (id<MKAnnotation> a in annotations) {
        ZAssert([a conformsToProtocol:@protocol(MKAnnotation)], @"ERROR: All elements of the array MUST conform to the MKAnnotation protocol. Element (%@) did not fulfill this requirement", a);
        MKMapPoint p = MKMapPointForCoordinate(a.coordinate);
        //MKMapRectUnion performs the union between 2 rects, returning a bigger rect containing both (or just one if the other is null). here we do it for rects without a size (points)
        r = MKMapRectUnion(r, MKMapRectMake(p.x, p.y, 0, 0));
    }

    [mapView setVisibleMapRect:r animated:animated];

}

@end

Gördüğünüz gibi, şu ana kadar 2 yöntem ekledim: haritanın görünür bölgesini MKMapView örneğindeki şu anda yüklü tüm ek açıklamalara uyacak şekilde ayarlamak için bir tane ve herhangi bir nesne dizisine ayarlamak için başka bir yöntem. MapView'in görünür bölgesini ayarlamak için kod şu kadar basit olacaktır:

   //the mapView instance  
    [self.mapView ij_setVisibleRectToFitAllLoadedAnnotationsAnimated:animated]; 

Umarım yardımcı olur =)


3

Bu sayfadaki tüm cevaplar haritanın tam ekranı kapladığını varsayar . Aslında haritanın üstüne bilgi veren bir HUD ekran (yani üst ve alt dağınık düğmeler) var .. ve böylece sayfadaki algoritmalar pimleri iyi gösterecektir, ancak bazıları HUD ekran düğmelerinin altında görünecektir .

Benim çözümüm için haritayı yakınlaştırır bir alt kümesinde ek açıklamalar görüntülemeyi ekranın ve çalışır farklı ekran boyutları (yani 3.5" 4.0" vs vs):

// create a UIView placeholder and throw it on top of the original mapview
// position the UIView to fit the maximum area not hidden by the HUD display buttons
// add an *other* mapview in that uiview, 
// get the MKCoordinateRegion that fits the pins from that fake mapview
// kill the fake mapview and set the region of the original map 
// to that MKCoordinateRegion.

İşte kod yaptım (not: i NSConstraintsbenim kod farklı ekran boyutlarında çalışması için bazı yardımcı yöntemleri ile kullanın .. kodu oldukça okunabilir iken .. burada cevabım daha iyi açıklıyor .. temelde aynı iş akışı :)

// position smallerMap to fit available space
// don't store this map, it will slow down things if we keep it hidden or even in memory
[@[_smallerMapPlaceholder] mapObjectsApplyingBlock:^(UIView *view) {
    [view removeFromSuperview];
    [view setTranslatesAutoresizingMaskIntoConstraints:NO];
    [view setHidden:NO];
    [self.view addSubview:view];
}];

NSDictionary *buttonBindingDict = @{ @"mapPlaceholder": _smallerMapPlaceholder};

NSArray *constraints = [@[@"V:|-225-[mapPlaceholder(>=50)]-176-|",
                          @"|-40-[mapPlaceholder(<=240)]-40-|"
                          ] mapObjectsUsingBlock:^id(NSString *formatString, NSUInteger idx){
                              return [NSLayoutConstraint constraintsWithVisualFormat:formatString options:0 metrics:nil views:buttonBindingDict];
                          }];

[self.view addConstraints:[constraints flattenArray]];
[self.view layoutIfNeeded];

MKMapView *smallerMap = [[MKMapView alloc] initWithFrame:self.smallerMapPlaceholder.frame];
[_smallerMapPlaceholder addSubview:smallerMap];

MKCoordinateRegion regionThatFits = [smallerMap getRegionThatFits:self.mapView.annotations];
[smallerMap removeFromSuperview];
smallerMap = nil;
[_smallerMapPlaceholder setHidden:YES];

[self.mapView setRegion:regionThatFits animated:YES];

İşte bölgeye uyan kodu alır:

- (MKCoordinateRegion)getRegionThatFits:(NSArray *)routes {
    MKCoordinateRegion region;
    CLLocationDegrees maxLat = -90.0;
    CLLocationDegrees maxLon = -180.0;
    CLLocationDegrees minLat = 90.0;
    CLLocationDegrees minLon = 180.0;
    for(int idx = 0; idx < routes.count; idx++)
    {
        CLLocation* currentLocation = [routes objectAtIndex:idx];
        if(currentLocation.coordinate.latitude > maxLat)
            maxLat = currentLocation.coordinate.latitude;
        if(currentLocation.coordinate.latitude < minLat)
            minLat = currentLocation.coordinate.latitude;
        if(currentLocation.coordinate.longitude > maxLon)
            maxLon = currentLocation.coordinate.longitude;
        if(currentLocation.coordinate.longitude < minLon)
            minLon = currentLocation.coordinate.longitude;
    }
    region.center.latitude     = (maxLat + minLat) / 2.0;
    region.center.longitude    = (maxLon + minLon) / 2.0;
    region.span.latitudeDelta = 0.01;
    region.span.longitudeDelta = 0.01;

    region.span.latitudeDelta  = ((maxLat - minLat)<0.0)?100.0:(maxLat - minLat);
    region.span.longitudeDelta = ((maxLon - minLon)<0.0)?100.0:(maxLon - minLon);

    MKCoordinateRegion regionThatFits = [self regionThatFits:region];
    return regionThatFits;
}

2

Rafael'in MKMapView Kategorisi kodunda küçük bir değişiklik yaptım .

- (void)zoomToFitMapAnnotations {
    if ([self.annotations count] == 0)
        return;

    CLLocationCoordinate2D topLeftCoord;
    topLeftCoord.latitude = -90;
    topLeftCoord.longitude = 180;

    CLLocationCoordinate2D bottomRightCoord;
    bottomRightCoord.latitude = 90;
    bottomRightCoord.longitude = -180;

    for (id <MKAnnotation> annotation in self.annotations) {
        topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
        topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);

        bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
        bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
    }

    MKCoordinateRegion region;
    region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
    region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
    region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; // Add a little extra space on the sides
    region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; // Add a little extra space on the sides

    [self setRegion:[self regionThatFits:region] animated:YES];
}

2

Yukarıdaki yanıtlara dayanarak, haritayı tüm ek açıklamalara ve yer paylaşımlarına aynı anda sığdırmak için evrensel yöntemi kullanabilirsiniz.

-(MKMapRect)getZoomingRectOnMap:(MKMapView*)map toFitAllOverlays:(BOOL)overlays andAnnotations:(BOOL)annotations includeUserLocation:(BOOL)userLocation {
    if (!map) {
        return MKMapRectNull;
    }

    NSMutableArray* overlaysAndAnnotationsCoordinateArray = [[NSMutableArray alloc]init];        
    if (overlays) {
        for (id <MKOverlay> overlay in map.overlays) {
            MKMapPoint overlayPoint = MKMapPointForCoordinate(overlay.coordinate);
            NSArray* coordinate = @[[NSNumber numberWithDouble:overlayPoint.x], [NSNumber numberWithDouble:overlayPoint.y]];
            [overlaysAndAnnotationsCoordinateArray addObject:coordinate];
        }
    }

    if (annotations) {
        for (id <MKAnnotation> annotation in map.annotations) {
            MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
            NSArray* coordinate = @[[NSNumber numberWithDouble:annotationPoint.x], [NSNumber numberWithDouble:annotationPoint.y]];
            [overlaysAndAnnotationsCoordinateArray addObject:coordinate];
        }
    }

    MKMapRect zoomRect = MKMapRectNull;
    if (userLocation) {
        MKMapPoint annotationPoint = MKMapPointForCoordinate(map.userLocation.coordinate);
        zoomRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
    }

    for (NSArray* coordinate in overlaysAndAnnotationsCoordinateArray) {
        MKMapRect pointRect = MKMapRectMake([coordinate[0] doubleValue], [coordinate[1] doubleValue], 0.1, 0.1);
        zoomRect = MKMapRectUnion(zoomRect, pointRect);
    }

    return zoomRect;
}

Ve sonra:

MKMapRect mapRect = [self getZoomingRectOnMap:mapView toFitAllOverlays:YES andAnnotations:YES includeUserLocation:NO];
[mapView setVisibleMapRect:mapRect edgePadding:UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0) animated:YES];

1

Sadece bu konudaki gözlemlerimi paylaşıyorum:

Film şeridinde ekranlar için "çıkartılmış" boyutlarda xCode> 6 kullanıyorsanız (bkz. Dosya denetçisinde "benzetilmiş metrikler")

- (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated

içinde viewDidLoadharita için düzen Storyboard'dan geniş ekranların büyüklüğü hala çünkü 4 inç sahip iPhone'lar üzerinde çok büyük bir yakınlaştırma düzeyinde sonuçlanacaktır.

Size çağrı taşıyabilirsiniz showAnnotations...için viewDidAppear. Ardından haritanın boyutu zaten bir iPhone 4'ün daha küçük ekranına ayarlandı.

Veya alternatif olarak, "benzetilmiş metrikler" altındaki dosya denetçisindeki "çıkartılmış" değerini iphone 4 inç olarak değiştirin.


1

Ek Açıklamalar ile birlikte hangi şekilleri göstermek istediğinizi seçebilirsiniz.

extension MKMapView {
  func setVisibleMapRectToFitAllAnnotations(animated: Bool = true,
                                            shouldIncludeUserAccuracyRange: Bool = true,
                                            shouldIncludeOverlays: Bool = true,
                                            edgePadding: UIEdgeInsets = UIEdgeInsets(top: 35, left: 35, bottom: 35, right: 35)) {
    var mapOverlays = overlays

    if shouldIncludeUserAccuracyRange, let userLocation = userLocation.location {
      let userAccuracyRangeCircle = MKCircle(center: userLocation.coordinate, radius: userLocation.horizontalAccuracy)
      mapOverlays.append(MKOverlayRenderer(overlay: userAccuracyRangeCircle).overlay)
    }

    if shouldIncludeOverlays {
      let annotations = self.annotations.filter { !($0 is MKUserLocation) }
      annotations.forEach { annotation in
        let cirlce = MKCircle(center: annotation.coordinate, radius: 1)
        mapOverlays.append(cirlce)
      }
    }

    let zoomRect = MKMapRect(bounding: mapOverlays)
    setVisibleMapRect(zoomRect, edgePadding: edgePadding, animated: animated)
  }
}

extension MKMapRect {
  init(bounding overlays: [MKOverlay]) {
    self = .null
    overlays.forEach { overlay in
      let rect: MKMapRect = overlay.boundingMapRect
      self = self.union(rect)
    }
  }
}

0

@ "Bunun uygulamamdaki diğer bazı faktörlerden kaynaklanıp kaynaklanmadığından emin değilim, ancak showAnnotations'ın manuel uygulamada olduğu gibi ek açıklamaların yakınlaştırılması / uygun hale getirilmemesi gerektiğini fark ettim, bu yüzden el ile bir - Ted Avery 17 Nisan, 0:35 "

Aynı sorunu yaşadım, ancak sonra showAnnotations'ı iki kez (aşağıda olduğu gibi) yapmaya çalıştım ve bir nedenle işe yaradı.

[mapView showAnnotations: animasyonluAnnotationArray öğeniz: YES]; [mapView showAnnotations: animasyonluAnnotationArray öğeniz: YES];


0

İOS 7 uyumlu bir yöntem aşağıdakileri kullanmaktır. showAnnotationTüm ek açıklamaları içeren bir dikdörtgen almak için ilk çağrı . Daha sonra ve UIEdgeInsetpin yüksekliğinin üst iç kısmı ile oluşturun . Böylece tüm pimi haritada göstermeyi garanti edersiniz.

[self.mapView showAnnotations:self.mapView.annotations animated:YES];
MKMapRect rect = [self.mapView visibleMapRect];
UIEdgeInsets insets = UIEdgeInsetsMake(pinHeight, 0, 0, 0);
[self.mapView setVisibleMapRect:rect edgePadding:insets animated:YES];

0

Bunu kodunuza ekleyin:

  - (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views
    {
    id<MKAnnotation> mp = [annotationView annotation];
        MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([mp coordinate] ,250,250);

       [mv setRegion:region animated:YES];

}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.