zoukankan      html  css  js  c++  java
  • (八十)MapKit放置系统默认大头针和自定义大头针

    有关MapView的显示和定位在上一节已经说明,这一节说明如何在地图上放置大头针,以及设置点击大头针的视图。

    【系统默认大头针】

    mapView上放置大头针的方法是调用其addAnnotation:方法,需要注意的是,传入的是模型而不是大头针视图。

    - (void)addAnnotation:(id <MKAnnotation>)annotation;
    通过这个方法,我们可以清楚的看到,annotation模型需要遵循MKAnnotation协议,我们打开这个协议,可以看到如下的内容:

    @protocol MKAnnotation <NSObject>
    
    // Center latitude and longitude of the annotation view.
    // The implementation of this property must be KVO compliant.
    @property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
    
    @optional
    
    // Title and subtitle for use by selection UI.
    @property (nonatomic, readonly, copy) NSString *title;
    @property (nonatomic, readonly, copy) NSString *subtitle;
    
    // Called as a result of dragging an annotation view.
    - (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate NS_AVAILABLE(10_9, 4_0);
    
    @end
    因此我们应当定义一个模型,按照协议定义这些属性,其中coordinate是必须定义的,因为大头针必须有位置。

    模型类遵循MKAnnocation协议,命名为MyAnnotation,如下:

    #import <Foundation/Foundation.h>
    #import <MapKit/MapKit.h>
    
    @interface MyAnnotation : NSObject<MKAnnotation>
     /**
     *  大头针的位置
     */
    @property (nonatomic, assign) CLLocationCoordinate2D coordinate;
    /**
     *  大头针标题
     */
    @property (nonatomic, copy) NSString *title;
    /**
     *  大头针的子标题
     */
    @property (nonatomic, copy) NSString *subtitle;
    @end
    #import "MyAnnotation.h"
    
    @implementation MyAnnotation
    
    @end


    然后就可以通过定义模型,调用addAnnotation:方法添加一枚大头针,例如我们通过Button,随机添加一枚大头针:

    - (IBAction)addPin:(id)sender {
        
        MyAnnotation *anno = [[MyAnnotation alloc] init];
        anno.title = @"title";
        anno.subtitle = @"subtitle";
        CLLocationDegrees latitude = 36.821119 + arc4random_uniform(20);
        CLLocationDegrees longtitude = 116.750112 + arc4random_uniform(20);
        anno.coordinate = CLLocationCoordinate2DMake(latitude, longtitude);
        
        [self.mapView addAnnotation:anno];
    }

    其中的title和subtitle是点击大头针时显示的气泡上的标题和副标题。

    大头针的显示原理和tableView显示cell是类似的,一旦调用addAnnotation:方法,就会调用mapView:viewForAnnotationView:方法,这个方法中应当从缓存池取出一个大头针视图,或者如果缓存池中没有新建一个大头针视图,然后返回。

    与tableView的区别是,如果直接返回nil,则会按照系统的样式返回大头针。

    需要注意的是,如果不返回nil,要对不同类型的大头针进行处理,不要忘了用户的位置指示圆点也属于一种大头针,如果只是单单的设置大头针,连用户位置也会是一颗针而不是圆点


    判断方法很简单,因为用户位置大头针由系统创建,因此传入的模型肯定不是我们自己的模型MyAnnotation,只要判断传入的模型是不是这个类,如果不是,则返回nil,代表按照系统默认样式,创建圆点。


    要创建大头针,使用的是MKPinAnnotationView,如果使用MKAnnotationView,是不带图片的,无法直接显示。

    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
        
        static NSString *ID = @"anno";
        // 如果返回nil,系统会按照默认方式显示,如果自定义,是无法直接显示的,并且点击大头针之后不会显示标题,需要自己手动设置显示
        // 如果想要直接显示,应该调用MKPinAnnotationView
        MKPinAnnotationView *annoView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID];
        
        if (annoView == nil) {
            annoView = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:ID];
            // 大头针属性
            annoView.animatesDrop = YES; // 设置大头针坠落的动画
            annoView.canShowCallout = YES; // 设置点击大头针是否显示气泡
            annoView.calloutOffset = CGPointMake(0, 0); // 设置大头针气泡的偏移
            // 设置大头针气泡的左右视图、可以为任意UIView
            annoView.leftCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
            annoView.rightCalloutAccessoryView = [[UISwitch alloc] init];
            [annoView setPinColor:MKPinAnnotationColorPurple]; // 设置大头针颜色
        }
        
        // 设置大头针的图片,如果是直接创建MKPin,则无效。
        //annoView.image = [UIImage imageNamed:@"pin"];
        
        annoView.annotation = annotation;
        
        // 如果是用户位置,应当显示默认的圆点而不是大头针,因此应当判断是否是MyAnnotation
        if(![annoView.annotation isKindOfClass:[MyAnnotation class]]){
            return nil;
        }
        
        return annoView;
        
    }

    【自定义大头针】

    自定义大头针需要使用MKAnnotationView,自己指定image,没有坠落动画,其他没有区别。

     (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
        
        static NSString *ID = @"anno";
        // 如果返回nil,系统会按照默认方式显示,如果自定义,是无法直接显示的,并且点击大头针之后不会显示标题,需要自己手动设置显示
        // 如果想要直接显示,应该调用MKPinAnnotationView
        MKAnnotationView *annoView = [mapView dequeueReusableAnnotationViewWithIdentifier:ID];
        
        if (annoView == nil) {
            annoView = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:ID];
            // 大头针属性
            //annoView.animatesDrop = YES; // MKPinAnnotaionView才有效,设置大头针坠落的动画
            annoView.canShowCallout = YES; // 设置点击大头针是否显示气泡
            annoView.calloutOffset = CGPointMake(0, 0); // 设置大头针气泡的偏移
            // 设置大头针气泡的左右视图、可以为任意UIView
            annoView.leftCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
            annoView.rightCalloutAccessoryView = [[UISwitch alloc] init];
            //[annoView setPinColor:MKPinAnnotationColorPurple]; // MKPinAnnotaionView才有效,设置大头针的颜色
        }
        
        // 设置大头针的图片
        annoView.image = [UIImage imageNamed:@"pin"];
        
        annoView.annotation = annotation;
        
        // 如果是用户位置,应当显示默认的圆点而不是大头针,因此应当判断是否是MyAnnotation
        if(![annoView.annotation isKindOfClass:[MyAnnotation class]]){
            return nil;
        }
        
        return annoView;
        
    }

    【MVC封装annotationView的注意点】

    annotation要传入模型,在重写的set方法里,注意调用父类的set方法,先设置公共属性,再设置自己所特有的。

    有一个细节,默认set方法的传入模型是id<MKAnnotaion>类型,在使用时还需要强转类型,为了方便,我们直接把类型改为MyAnnotation,因为OC在调用方法时发送的消息只包括方法名和冒号、描述,因此类型不属于方法名的一部分,可以修改。

    - (void)setAnnotation:(MyAnnotation *)annotation{
       [super setAnnotation:annotation];
       // 设置特有的属性,例如图片、左右视图等。
    }


  • 相关阅读:
    CF1051F The Shortest Statement 题解
    CF819B Mister B and PR Shifts 题解
    HDU3686 Traffic Real Time Query System 题解
    HDU 5969 最大的位或 题解
    P3295 萌萌哒 题解
    BZOJ1854 连续攻击游戏 题解
    使用Python编写的对拍程序
    CF796C Bank Hacking 题解
    BZOJ2200 道路与航线 题解
    USACO07NOV Cow Relays G 题解
  • 原文地址:https://www.cnblogs.com/aiwz/p/6154121.html
Copyright © 2011-2022 走看看