地图与定位(三)自定义大头针视图

本文介绍了如何自定义MKMapView的大头针视图,包括通过代理方法`mapView:viewForAnnotation:`创建自定义MKAnnotationView,以及如何通过子类化MKPinAnnotationView添加大头针图片和动画。此外,还讲解了如何实现大头针详情视图的自定义,通过添加新的大头针模型并在代理方法中判断并返回自定义视图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 自定义大头针视图

前文中,我们看到添加的大头针在地图上显示的形式都是一样的,采用系统默认的大头针样式。在一些应用中系统默认的大头针样式可能无法满足实际的需求,此时就需要修改大头针视图默认样式。事实上,MKMapView的代理方法- (MKAnnotationView )mapView:(MKMapView )mapView viewForAnnotation:(id )annotation;可以返回一个大头针视图,只要实现这个方法并在这个方法中定义一个大头针视图MKAnnotationView对象并设置相关属性就可以改变默认大头针的样式。当然如果代理方法返回nil则会使用默认大头针视图,需要根据情况设置,比如添加的大头针数据为用户当前位置(MKUserAnnotation)。

通过上面的代理方法自定义大头针视图需要注意代理方法的调用时机:每当有大头针显示到系统可视界面中时就会调用此方法返回一个大头针视图放到界面中,同时当前系统位置标注(也就是地图中蓝色的位置点)也是一个大头针,也会调用此方法,因此处理大头针视图时需要区别对待(通过大头针数据模型)。另外类似于UITableView的代理方法,此方法调用频繁,开发过程中需要重复利用MapKit的缓存池将大头针视图缓存起来重复利用。自定义大头针默认情况下不允许交互,如果交互需要设置属性显示大头针视图的标题以区分大头针视图。下面是MKAnnotationView的常用属性:

属性 说明
annotation 大头针模型信息,包括标题、子标题、地理位置。
image 大头针图片
canShowCallout 点击大头针是否显示标题、子标题内容等,注意如果在- (MKAnnotationView )mapView:(MKMapView )mapView viewForAnnotation:(id )annotation;方法中重新定义大头针默认情况是无法交互的需要设置为true。
calloutOffset 点击大头针时弹出详情信息视图的偏移量
selected 是否被选中状态
leftCalloutAccessoryView 弹出详情左侧视图
rightCalloutAccessoryView 弹出详情右侧视图

从上面的属性中,我们不难看出,当我们自定义大头针视图时,除了可以添加大头针的图片之外,我们还可以设置更多的大头针视图属性,比如弹出视图、偏移量等信息。

示例代码:
自定义大头针数据模型:
Annotation.h 大头针数据模型

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface Annotation : NSObject<MKAnnotation>

@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;

// 自定义一个图片属性在创建大头针视图时使用
@property (nonatomic, copy)NSString *imageName;

@end

添加大头针数据,并返回大头针视图

#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#import "Annotation.h"

@interface ViewController ()<CLLocationManagerDelegate,MKMapViewDelegate>

@property (nonatomic, strong)CLLocationManager *locationManager;
@property (nonatomic, strong)MKMapView *mapView;

@end

@implementation ViewController

- (CLLocationManager *)locationManager {

    if (!_locationManager) {
        _locationManager = [[CLLocationManager alloc] init];
        _locationManager.delegate = self;
    }
    return _locationManager;
}

- (MKMapView *)mapView {

    if (!_mapView) {
        _mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
        //设置地图样式
        _mapView.mapType = MKMapTypeStandard;
        //设置用于追踪模式
        _mapView.userTrackingMode = MKUserTrackingModeFollow;
        _mapView.delegate = self;
    }
    return _mapView;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.view addSubview:self.mapView];

    //1.判断手机定位服务是否打开
    if (![CLLocationManager locationServicesEnabled]) {
        NSLog(@"手机定位服务没有打开");
        return;
    }

    //2.iOS8.0以上的用户需要授权
    if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
        if ([[[UIDevice currentDevice]  systemVersion] floatValue] >= 8.0) {
            //调用此方法之前必须在plist文件中添加NSLocationWhenInUseUsageDescription --string-- 后面跟的文字就是提示信息
            [self.locationManager requestWhenInUseAuthorization];
        }
    }
}
// 添加大头针数据模型
- (void)addAnnotation {

    // 酒店大头针数据
    Annotation *anno1 = [[Annotation alloc] init];
    anno1.coordinate = CLLocationCoordinate2DMake(39.9, 116);
    anno1.title = @"xxx酒店";
    anno1.subtitle = @"周末8折,会员5折";
    anno1.imageName = @"category_3";
    [self.mapView addAnnotation:anno1];

    // 影院大头针
    Annotation *anno2 = [[Annotation alloc] init];
    anno2.coordinate = CLLocationCoordinate2DMake(40, 117);
    anno2.title = @"xxx影院";
    anno2.subtitle = @"《夏洛 特 烦恼》 正在热映,周末免费";
    anno2.imageName = @"category_5";
    [self.mapView addAnnotation:anno2];
}

#pragma mapViewDelegate
/**
 *  用户位置发生改变的时候调用这个方法
 *
 *  @param mapView      地图
 *  @param userLocation 地图上蓝色的那颗大头针数据(注意不是那个蓝色的视图)
 */
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    userLocation.title = @"北京市";
    userLocation.subtitle = @"中国首都";
    NSLog(@"%f , %f",userLocation.location.coordinate.latitude,userLocation.location.coordinate.longitude);

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        //设置地图显示的区域
        //获取中心点位置
        CLLocationCoordinate2D center = userLocation.location.coordinate;
        //显示跨度
        MKCoordinateSpan span = MKCoordinateSpanMake(4.193344, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值