Memperbesar MKMapView agar pas dengan pin anotasi?

193

Saya menggunakan MKMapView dan telah menambahkan sejumlah pin anotasi ke peta sekitar 5-10 kilometer. Ketika saya menjalankan aplikasi, peta saya mulai diperbesar untuk menunjukkan seluruh dunia, apa cara terbaik untuk memperbesar peta sehingga pin sesuai dengan tampilan?

EDIT: Pemikiran awal saya adalah menggunakan MKCoordinateRegionMake dan menghitung pusat koordinat, bujurDelta, dan latitudeDelta dari anotasi saya. Saya cukup yakin ini akan berhasil, tetapi saya hanya ingin memeriksa bahwa saya tidak melewatkan sesuatu yang jelas.

Kode ditambahkan, BTW: FGLocation adalah kelas yang sesuai dengan MKAnnotation, locationFake adalah salah satu NSMutableArraydari objek-objek ini. Komentar selalu diterima ....

- (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;
}
fuzzygoat
sumber
10
Catatan iOS 7: Metode showAnnotations: animated: baru dapat membantu Anda menghindari perhitungan wilayah manual ini.

Jawaban:

123

Anda benar.

Temukan garis lintang dan bujur maksimum dan minimum Anda, terapkan beberapa aritmatika sederhana, dan gunakan MKCoordinateRegionMake.

Untuk iOS 7 dan di atasnya, gunakan showAnnotations:animated:, dari 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);
Matthew Frederick
sumber
158
Untuk iOS 7 dan yang lebih baru (Merujuk 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
Ini berfungsi dengan baik tetapi kadang-kadang ketika saya memperbesar (di peta) kemudian mencoba memusatkannya (menggunakan tombol yang memanggil metode ini) sepertinya tidak berfungsi.
RPM
5
Penting untuk dicatat bahwa showAnnotationsjuga menambahkan anotasi ke peta, bahkan jika anotasi untuk lokasi itu sudah ada.
Eneko Alonso
@EnekoAlonso Anda dapat mengatasi ini dengan menelepon removeAnnotations(_ annotations:)segera setelahshowAnnotations(_ annotations:animated)
Alain Stulz
1
Juga patut dicatat adalah bahwa sementara showAnnotations mengatur wilayah untuk menampilkan anotasi, wilayah tersebut masih akan disesuaikan agar sesuai dengan rasio aspek; dan ini akan sering mengecualikan beberapa penjelasan. Perhatikan juga bahwa showAnnotations adalah satu-satunya solusi yang benar yang disajikan di sini; tidak ada jawaban lain yang bahkan berusaha menangani anotasi yang mencakup garis tanggal internasional.
Gordon Dove
335

Ini yang saya temukan di sini yang bekerja untuk saya:

(EDIT: Saya telah memperbarui solusi menggunakan saran @ Micah untuk meningkatkan pointRect sebesar 0,1 untuk memastikan persegi tidak berakhir menjadi sangat kecil!)

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];

 

Anda juga dapat memperbarui ini untuk memasukkan pin userLocation dengan mengganti baris pertama dengan:

MKMapPoint annotationPoint = MKMapPointForCoordinate(mapView.userLocation.coordinate);
MKMapRect zoomRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
jowie
sumber
4
Bagus dong. Anda tidak perlu memeriksa isNull sekalipun. MKMapRectUnion melakukan ini untuk Anda. Dari dokumen: "Jika salah satu persegi panjang adalah nol, metode ini mengembalikan persegi panjang lainnya."
Felix Lamouroux
37
Solusi yang sangat bagus !!! Ini sedikit sentuhan ekstra untuk menambahkan beberapa lapisan: double inset = -zoomRect.size.width * 0,1; [self.mapView setVisibleMapRect: MKMapRectInset (zoomRect, inset, inset) dianimasikan: YA];
Craig B
1
Luar biasa! Tambahan potensial: jika Anda ingin mengecualikan 'anotasi lokasi saat ini' cukup tambahkan pernyataan if dalam for for loop: if (! [Anotasi isKindOfClass: [kelas MKUserLocation]]) {// Lakukan hal-hal di sini}
kgaidis
2
Solusi @CraigB untuk bantalan sangat baik, tetapi tidak berfungsi dengan baik ketika jalur vertikal, misalnya gerakan dari selatan ke utara, untuk memperbaiki ini gunakan double inset = MIN (-zoomRect.size.width * 0,1, -zoomRect.size. tinggi * 0,1);
Farhad Malekpour
1
Peningkatan dengan padding: double insetWidth = -zoomRect.size.width * 0.2; double insetHeight = -zoomRect.size.height * 0.2; MKMapRect insetRect = MKMapRectInset (zoomRect, insetWidth, insetHeight); Kemudian gunakan insertRect baru ini
dulgan
121

Apple telah menambahkan metode baru untuk iOS 7 untuk menyederhanakan hidup sedikit.

[mapView showAnnotations:yourAnnotationArray animated:YES];

Anda dapat dengan mudah menarik dari array yang tersimpan di tampilan peta:

yourAnnotationArray = mapView.annotations;

dan sesuaikan kamera dengan cepat juga!

mapView.camera.altitude *= 1.4;

ini tidak akan berfungsi kecuali pengguna menginstal iOS 7+ atau OS X 10.9+. lihat animasi khusus di sini

Ryan Berg
sumber
Saya tidak yakin apakah ini karena beberapa faktor lain dalam implementasi saya, tetapi saya menemukan bahwa showAnnotationsitu tidak melakukan zoom / fit anotasi seperti halnya implementasi manual, jadi saya terjebak dengan yang manual.
Ted Avery
1
coba gandakan ketinggian kamera dengan sepersekiannya, seperti mapView.camera.altitude * = .85; untuk viewport yang lebih dekat
Ryan Berg
Saya juga menemukan ini berguna untuk memilih anotasi di luar area peta yang terlihat saat ini. Secara default, MapView tidak memilih anotasi yang tidak terlihat. Panggil showAnnotations dengan larik anotasi yang tidak terlihat, sebelum memanggil selectAnnotation, dan peta harus memperbarui area yang terlihat.
MandisaW
42

Saya menggunakan kode ini dan berfungsi dengan baik untuk saya:

-(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];
}
Rafael Moreira
sumber
Jangan bekerja untuk: ▿ 2 elemen ▿ 0: CLLocationCoordinate2D - lintang: 46.969995730376894 - bujur: -109.2494943434474 ▿ 1: CLLocationCoordinate2D - lintang: 63.23212154333072 - bujur: 174.13666611126533
bujur
23

Sedang digunakan Swift

mapView.showAnnotations(annotationArray, animated: true)

Dalam Tujuan c

[mapView showAnnotations:annotationArray animated:YES];
Sreedeepkesav MS
sumber
2
Jika anotasi telah ditetapkan pada mapView, Anda dapat merujuknya langsung ke:mapView.showAnnotations(mapView.annotations, animated: true)
Justin Vallely
14

Saya telah mengonversi jawaban oleh Rafael Moreira. Penghargaan itu jatuh padanya. Bagi Anda yang mencari versi Swift, berikut ini kodenya:

 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)
}
Prashant Khanal
sumber
14

Swift 3 Ini adalah cara yang benar untuk memuat semua anotasi di peta.

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)

    }
castellon oscar
sumber
@ArshadShaik Suntingan yang Anda sarankan telah ditolak, jika Anda ingin memberikan jawaban baru untuk Swift 4.2, silakan saja, tetapi tambahkan sebagai jawaban, bukan dengan mengeditnya di pos pengguna lain.
Nick
13

Solusi @ jowie bekerja sangat baik. Satu tangkapan, jika peta hanya memiliki satu anotasi, Anda akan berakhir dengan peta yang diperbesar sepenuhnya. Saya menambahkan 0,1 ke ukuran make rect untuk memastikan setVisibleMapRect memiliki sesuatu untuk diperbesar.

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

Jika Anda mencari iOS 8 ke atas , cara paling sederhana untuk melakukannya adalah dengan mengatur var layoutMargins: UIEdgeInsets { get set }tampilan peta Anda sebelum meneleponfunc showAnnotations(annotations: [MKAnnotation], animated: Bool)

Misalnya (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)
}
Henrik Perrochon
sumber
12

Saya membuat ekstensi untuk menunjukkan semua anotasi menggunakan beberapa kode dari sana-sini dengan cepat. Ini tidak akan menampilkan semua anotasi jika mereka tidak dapat ditampilkan bahkan pada tingkat zoom maksimum.

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)
    }
}
Ankit Srivastava
sumber
Saya berhasil mendapatkan hasil yang lebih baik dengan mengubah UIEdgeInsetsMakeparameter, nilai antara 30 dan 100 bagus untuk saya. Saya sedang menguji menggunakan iPhone SE i) S 10.2 Simulator. Contoh kode: setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(100, 100, 100, 100), animated: true). Sebagai catatan, Kode Ini Berfungsi di Swift 3 dan XCode 8.2.1.
nyxee
8

Menambahkan loop If ini dalam for loop untuk mengecualikan pin lokasi pengguna dari metode ini (diperlukan dalam kasus saya, dan mungkin yang lain)

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

//Code Here...

}
Sammio2
sumber
8

Untuk iOS 7 dan yang lebih baru (Merujuk 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);

komentar dari - Abhishek Bedi

Anda baru saja menelepon:

 [yourMapView showAnnotations:@[yourAnnotation] animated:YES];
Seke1412
sumber
Hanya untuk referensi, teks NS_AVAILABLE ada di sana karena pada Januari 2011, memiliki iOS 7 pada perangkat tidak mungkin, dan NS_AVAILABLE melindungi aplikasi dari kegagalan atau kerusakan build.
Matthew Frederick
5

Dalam Swift

    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)
Matheus Domingos
sumber
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)

// Diedit untuk cepat 5

alicanbatur
sumber
4

Berkat jowie saya telah memperbarui kategori lama saya ke solusi yang lebih elegan. Berbagi solusi lengkap, hampir salin & tempel

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

Semoga ini bisa membantu seseorang dan terima kasih lagi jowie!

JakubKnejzlik
sumber
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];

}
Ravi Karadbhajane
sumber
4

Seperti yang ditunjukkan Abhishek Bedi dalam komentar, Untuk iOS7, cara terbaik untuk melakukan ini adalah:

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

Untuk proyek pribadi saya (sebelum iOS7) saya cukup menambahkan kategori pada kelas MKMapView untuk merangkum fungsionalitas "area tampak" untuk operasi yang sangat umum: mengaturnya agar dapat melihat semua anotasi yang saat ini dimuat pada instance MKMapView ( ini termasuk pin sebanyak yang mungkin Anda tempatkan, serta lokasi pengguna). hasilnya adalah ini:

file .h

#import <MapKit/MapKit.h>

@interface MKMapView (Extensions)

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


@end

file .m

#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

Seperti yang Anda lihat, saya telah menambahkan 2 metode sejauh ini: satu untuk mengatur wilayah peta yang terlihat ke yang cocok dengan semua anotasi yang dimuat saat ini pada instance MKMapView, dan metode lain untuk mengaturnya ke berbagai objek. Jadi untuk mengatur wilayah yang terlihat dari mapView maka kode akan sesederhana:

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

Saya harap ini membantu =)

Robertibiris
sumber
3

Semua jawaban di halaman ini mengasumsikan bahwa peta tersebut menempati layar penuh . Saya sebenarnya memiliki tampilan HUD (yaitu tombol yang tersebar di bagian atas dan bawah) yang memberikan informasi di atas peta .. dan algoritma pada halaman akan menampilkan pin dengan benar, tetapi beberapa di antaranya akan muncul di bawah tombol tampilan HUD .

Solusi saya memperbesar peta untuk menampilkan anotasi dalam subset layar dan berfungsi untuk berbagai ukuran layar (mis. 3,5 "vs 4,0" dll):

// 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.

Berikut adalah apa yang saya lakukan dalam kode (catatan: saya gunakan NSConstraintsdengan beberapa metode pembantu untuk membuat kode saya bekerja dalam ukuran layar yang berbeda .. sementara kode ini cukup mudah dibaca .. jawaban saya di sini menjelaskan lebih baik .. itu pada dasarnya alur kerja yang sama :)

// 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];

di sini adalah kode yang mendapat wilayah yang cocok:

- (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;
}
abbood
sumber
2

Saya telah membuat sedikit modifikasi kode Rafael untuk Kategori MKMapView.

- (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];
}
Kirow
sumber
2

Berdasarkan jawaban di atas Anda dapat menggunakan metode universal untuk memperbesar peta agar sesuai dengan semua anotasi dan overlay pada saat yang bersamaan.

-(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;
}

Lalu:

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];
Alexander Korotkov
sumber
1

Cukup bagikan pengamatan saya tentang ini:

Jika Anda menggunakan xCode> 6 dengan ukuran "disimpulkan" untuk layar (lihat "metrik simulasi" pada inspektur file) di storyboard, menelepon

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

in viewDidLoadakan menghasilkan tingkat zoom terlalu besar pada iPhone dengan 4 inci karena tata letak untuk peta masih pada ukuran layar yang lebih luas dari storyboard.

Anda dapat memindahkan panggilan showAnnotations...ke viewDidAppear. Kemudian ukuran peta telah disesuaikan dengan layar iPhone 4 yang lebih kecil.

Atau sebagai alternatif ubah nilai "disimpulkan" di inspektur file di bawah "metrik simulasi" menjadi iphone 4-inci.

Jens
sumber
1

Anda dapat memilih bentuk mana yang ingin Anda tampilkan bersama dengan Anotasi.

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)
    }
  }
}
Anirudha Mahale
sumber
0

@ "Saya tidak yakin apakah ini karena beberapa faktor lain dalam implementasi saya, tetapi saya menemukan bahwa showAnnotations tidak melakukan zoom / fit dari anotasi seperti halnya implementasi manual, jadi saya terjebak dengan manual satu -. Ted Avery 17 Apr jam 0:35 "

Saya memiliki masalah yang sama, tetapi kemudian saya mencoba melakukan showAnnotations dua kali (seperti di bawah), dan untuk beberapa alasan, itu berhasil.

[mapView showAnnotations: yourAnnotationArray animated: YES]; [mapView showAnnotations: yourAnnotationArray animated: YES];

zakton
sumber
0

Cara yang kompatibel dengan iOS 7 adalah menggunakan yang berikut ini. Panggilan pertama showAnnotationuntuk mendapatkan persegi panjang termasuk semua penjelasan. Setelah itu buat dan UIEdgeInsetdengan inset tinggi pin. Dengan demikian, Anda memastikan untuk menampilkan seluruh pin pada peta.

[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];
Morpheus78
sumber
0

Masukkan ini ke kode Anda sesuai:

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

       [mv setRegion:region animated:YES];

}
Abhishek Bedi
sumber