美文网首页其它技术点开发技巧iOS
【iOS】高德地图MAMapKit的使用:导航功能。

【iOS】高德地图MAMapKit的使用:导航功能。

作者: attackGiant | 来源:发表于2017-03-10 17:00 被阅读2945次

    http://www.jianshu.com/p/73a6acba45aa 之后的导航功能。

    93039.png

    线路规划主要代码:

     //进行路径规划
        [self.driveManager calculateDriveRouteWithStartPoints:@[self.startPoint]
                                                    endPoints:@[self.endPoint]
                                                    wayPoints:nil
                                              drivingStrategy:AMapNaviDrivingStrategySingleDefault];
    

    接下来叙述项目配置:
    1、去高德开放平台下载对应的导航AMapNaviKit.framework并解压

    21112.png

    2、将AMapNaviKit.framework拖入工程,记得选择:

    121212.png

    3、添加导航需要的资源文件 AMapNavi.bundle,如图:

    223.png 323.png

    4、下面开始代码部分:(自定义控制器,将下面的代码复制进控制器即可,只需要在上个控制器设置好CLLocationCoordinate2D coor、MAUserLocation *currentUL即可进行导航功能)
    在导航控制器.h文件导入头文件#import <AMapNaviKit/AMapNaviKit.h>并添加几个属性:

    @property (nonatomic, strong) AMapNaviDriveManager *driveManager;
    
    @property (nonatomic, strong) AMapNaviDriveView *driveView;
    
    @property (nonatomic, strong) MAUserLocation *currentUL;//导航起始位置,即用户当前的位置
    
    @property (nonatomic, assign) CLLocationCoordinate2D coor;//导航终点位置
    

    导航控制器.m文件:

    
    #import "SpeechSynthesizer.h"
    #import "MoreMenuView.h"
    
    @interface GPSNaviViewController ()<AMapNaviDriveManagerDelegate, AMapNaviDriveViewDelegate, MoreMenuViewDelegate>
    
    @property (nonatomic, strong) AMapNaviPoint *startPoint;
    @property (nonatomic, strong) AMapNaviPoint *endPoint;
    
    @property (nonatomic, strong) MoreMenuView *moreMenu;
    
    @end
    
    @implementation GPSNaviViewController
    
    #pragma mark - Life Cycle
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
    //    [self setNavigationBackItem];
        
        [self initProperties];
        
        [self initDriveView];
        
        [self initDriveManager];
        
        [self initMoreMenu];
    }
    
    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
        
        self.navigationController.navigationBarHidden = YES;
        self.navigationController.toolbarHidden = YES;
    }
    
    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        
        [self calculateRoute];
    }
    
    - (void)viewWillLayoutSubviews
    {
        UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
        if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0)
        {
            interfaceOrientation = self.interfaceOrientation;
        }
        
        if (UIInterfaceOrientationIsPortrait(interfaceOrientation))
        {
            [self.driveView setIsLandscape:NO];
        }
        else if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
        {
            [self.driveView setIsLandscape:YES];
        }
    }
    
    - (BOOL)prefersStatusBarHidden
    {
        return YES;
    }
    
    #pragma mark - Initalization
    
    - (void)initProperties
    {
        //设置导航的起点和终点
        self.startPoint = [AMapNaviPoint locationWithLatitude:_currentUL.coordinate.latitude longitude:_currentUL.coordinate.longitude];
        self.endPoint   = [AMapNaviPoint locationWithLatitude:_coor.latitude longitude:_coor.longitude];
    }
    
    - (void)initDriveManager
    {
        if (self.driveManager == nil)
        {
            self.driveManager = [[AMapNaviDriveManager alloc] init];
            [self.driveManager setDelegate:self];
            
            [self.driveManager setAllowsBackgroundLocationUpdates:YES];
            [self.driveManager setPausesLocationUpdatesAutomatically:NO];
            
            //将driveView添加为导航数据的Representative,使其可以接收到导航诱导数据
            [self.driveManager addDataRepresentative:self.driveView];
        }
    }
    
    - (void)initDriveView
    {
        if (self.driveView == nil)
        {
            self.driveView = [[AMapNaviDriveView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
            self.driveView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
            [self.driveView setDelegate:self];
            
            [self.view addSubview:self.driveView];
        }
    }
    
    - (void)initMoreMenu
    {
        if (self.moreMenu == nil)
        {
            self.moreMenu = [[MoreMenuView alloc] init];
            self.moreMenu.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
            
            [self.moreMenu setDelegate:self];
        }
    }
    
    #pragma mark - Route Plan
    
    - (void)calculateRoute
    {
        //进行路径规划
        [self.driveManager calculateDriveRouteWithStartPoints:@[self.startPoint]
                                                    endPoints:@[self.endPoint]
                                                    wayPoints:nil
                                              drivingStrategy:AMapNaviDrivingStrategySingleDefault];
    }
    
    #pragma mark - AMapNaviDriveManager Delegate
    
    - (void)driveManager:(AMapNaviDriveManager *)driveManager error:(NSError *)error
    {
        NSLog(@"error:{%ld - %@}", (long)error.code, error.localizedDescription);
    }
    
    - (void)driveManagerOnCalculateRouteSuccess:(AMapNaviDriveManager *)driveManager
    {
        NSLog(@"onCalculateRouteSuccess");
        
        //算路成功后开始GPS导航
        [self.driveManager startGPSNavi];
    }
    
    - (void)driveManager:(AMapNaviDriveManager *)driveManager onCalculateRouteFailure:(NSError *)error
    {
        NSLog(@"onCalculateRouteFailure:{%ld - %@}", (long)error.code, error.localizedDescription);
    }
    
    - (void)driveManager:(AMapNaviDriveManager *)driveManager didStartNavi:(AMapNaviMode)naviMode
    {
        NSLog(@"didStartNavi");
    }
    
    - (void)driveManagerNeedRecalculateRouteForYaw:(AMapNaviDriveManager *)driveManager
    {
        NSLog(@"needRecalculateRouteForYaw");
    }
    
    - (void)driveManagerNeedRecalculateRouteForTrafficJam:(AMapNaviDriveManager *)driveManager
    {
        NSLog(@"needRecalculateRouteForTrafficJam");
    }
    
    - (void)driveManager:(AMapNaviDriveManager *)driveManager onArrivedWayPoint:(int)wayPointIndex
    {
        NSLog(@"onArrivedWayPoint:%d", wayPointIndex);
    }
    
    - (void)driveManager:(AMapNaviDriveManager *)driveManager playNaviSoundString:(NSString *)soundString soundStringType:(AMapNaviSoundType)soundStringType
    {
        NSLog(@"playNaviSoundString:{%ld:%@}", (long)soundStringType, soundString);
        
        [[SpeechSynthesizer sharedSpeechSynthesizer] speakString:soundString];
    }
    
    - (void)driveManagerDidEndEmulatorNavi:(AMapNaviDriveManager *)driveManager
    {
        NSLog(@"didEndEmulatorNavi");
    }
    
    - (void)driveManagerOnArrivedDestination:(AMapNaviDriveManager *)driveManager
    {
        NSLog(@"onArrivedDestination");
    }
    
    #pragma mark - AMapNaviWalkViewDelegate
    
    - (void)driveViewCloseButtonClicked:(AMapNaviDriveView *)driveView
    {
        //停止导航
        [self.driveManager stopNavi];
        [self.driveManager removeDataRepresentative:self.driveView];
                 
        //停止语音
        [[SpeechSynthesizer sharedSpeechSynthesizer] stopSpeak];
        
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    - (void)driveViewMoreButtonClicked:(AMapNaviDriveView *)driveView
    {
        //配置MoreMenu状态
        [self.moreMenu setTrackingMode:self.driveView.trackingMode];
        [self.moreMenu setShowNightType:self.driveView.showStandardNightType];
        
        [self.moreMenu setFrame:self.view.bounds];
        [self.view addSubview:self.moreMenu];
    }
    
    - (void)driveViewTrunIndicatorViewTapped:(AMapNaviDriveView *)driveView
    {
        NSLog(@"TrunIndicatorViewTapped");
    }
    
    - (void)driveView:(AMapNaviDriveView *)driveView didChangeShowMode:(AMapNaviDriveViewShowMode)showMode
    {
        NSLog(@"didChangeShowMode:%ld", (long)showMode);
    }
    
    #pragma mark - MoreMenu Delegate
    
    - (void)moreMenuViewFinishButtonClicked
    {
        [self.moreMenu removeFromSuperview];
    }
    
    - (void)moreMenuViewNightTypeChangeTo:(BOOL)isShowNightType
    {
        [self.driveView setShowStandardNightType:isShowNightType];
    }
    
    - (void)moreMenuViewTrackingModeChangeTo:(AMapNaviViewTrackingMode)trackingMode
    {
        [self.driveView setTrackingMode:trackingMode];
    }
    

    在导航控制器.m文件中引用的#import "SpeechSynthesizer.h" 为导航时的语音功能、

    import "MoreMenuView.h"为偏好设置界面

    0383.png

    SpeechSynthesizer.h文件内容:

    #import <AVFoundation/AVFoundation.h>
    
    /**
     *  iOS7及以上版本可以使用 AVSpeechSynthesizer 合成语音
     *
     *  或者采用"科大讯飞"等第三方的语音合成服务
     */
    @interface SpeechSynthesizer : NSObject
    
    + (instancetype)sharedSpeechSynthesizer;
    
    - (void)speakString:(NSString *)string;
    
    - (void)stopSpeak;
    

    SpeechSynthesizer.m文件内容:

    @interface SpeechSynthesizer () <AVSpeechSynthesizerDelegate>
    
    @property (nonatomic, strong, readwrite) AVSpeechSynthesizer *speechSynthesizer;
    
    @end
    
    @implementation SpeechSynthesizer
    
    + (instancetype)sharedSpeechSynthesizer
    {
        static id sharedInstance = nil;
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedInstance = [[SpeechSynthesizer alloc] init];
        });
        return sharedInstance;
    }
    
    - (instancetype)init
    {
        if (self = [super init])
        {
            [self buildSpeechSynthesizer];
        }
        return self;
    }
    
    - (void)buildSpeechSynthesizer
    {
        if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0)
        {
            return;
        }
        
        //简单配置一个AVAudioSession以便可以在后台播放声音,更多细节参考AVFoundation官方文档
        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session setCategory:AVAudioSessionCategoryPlayback error:NULL];
        
        self.speechSynthesizer = [[AVSpeechSynthesizer alloc] init];
        [self.speechSynthesizer setDelegate:self];
    }
    
    - (void)speakString:(NSString *)string
    {
        if (self.speechSynthesizer)
        {
            AVSpeechUtterance *aUtterance = [AVSpeechUtterance speechUtteranceWithString:string];
            [aUtterance setVoice:[AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"]];
            
            //iOS语音合成在iOS8及以下版本系统上语速异常
            if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0)
            {
                aUtterance.rate = 0.25;//iOS7设置为0.25
            }
            else if ([[[UIDevice currentDevice] systemVersion] floatValue] < 9.0)
            {
                aUtterance.rate = 0.15;//iOS8设置为0.15
            }
            
            if ([self.speechSynthesizer isSpeaking])
            {
                [self.speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryWord];
            }
            
            [self.speechSynthesizer speakUtterance:aUtterance];
        }
    }
    
    - (void)stopSpeak
    {
        if (self.speechSynthesizer)
        {
            [self.speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
        }
    }
    

    MoreMenuView.h文件内容:

    #import <AMapNaviKit/AMapNaviCommonObj.h>
    
    @protocol MoreMenuViewDelegate;
    
    @interface MoreMenuView : UIView
    
    @property (nonatomic, assign) id<MoreMenuViewDelegate> delegate;
    
    @property (nonatomic, assign) AMapNaviViewTrackingMode trackingMode;
    @property (nonatomic, assign) BOOL showNightType;
    
    @end
    
    @protocol MoreMenuViewDelegate <NSObject>
    @optional
    
    - (void)moreMenuViewFinishButtonClicked;
    - (void)moreMenuViewTrackingModeChangeTo:(AMapNaviViewTrackingMode)trackingMode;
    - (void)moreMenuViewNightTypeChangeTo:(BOOL)isShowNightType;
    

    MoreMenuView.m文件内容:

    #define kFinishButtonHeight     40.0f
    #define kOptionTableViewHieght  200.0f
    #define kTableViewHeaderHeight  30.0f
    #define kTableViewCellHeight    50.0f
    
    @interface MoreMenuView ()<UITableViewDataSource, UITableViewDelegate>
    {
        UIView *_maskView;
        
        UITableView *_optionTableView;
        NSArray *_sections;
        NSArray *_options;
        
        UISegmentedControl *_viewModeSeg;
        UISegmentedControl *_nightTypeSeg;
        
        UIButton *_finishButton;
    }
    
    @end
    
    @implementation MoreMenuView
    
    @synthesize trackingMode = _trackingMode;
    @synthesize showNightType = _showNightType;
    
    #pragma mark - Initialization
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame])
        {
            self.backgroundColor = [UIColor clearColor];
            
            [self initProperties];
            
            [self createMoreMenuView];
        }
        
        return self;
    }
    
    - (void)initProperties
    {
        _sections = @[@"偏好设置"];
        
        _options = @[@[@"跟随模式", @"昼夜模式"]];
    }
    
    - (void)createMoreMenuView
    {
        [self initMaskView];
        
        [self initTableView];
        
        [self initFinishButton];
    }
    
    - (void)initMaskView
    {
        _maskView = [[UIView alloc] initWithFrame:self.bounds];
        _maskView.backgroundColor = [UIColor grayColor];
        _maskView.alpha = 0.5;
        _maskView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        
        [self addSubview:_maskView];
    }
    
    - (void)initTableView
    {
        _optionTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.bounds) - kFinishButtonHeight - kOptionTableViewHieght, CGRectGetWidth(self.bounds), kOptionTableViewHieght)
                                                        style:UITableViewStylePlain];
        _optionTableView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
        _optionTableView.backgroundColor = [UIColor whiteColor];
        _optionTableView.delegate = self;
        _optionTableView.dataSource = self;
        _optionTableView.allowsSelection = NO;
        
        [self addSubview:_optionTableView];
    }
    
    - (void)initFinishButton
    {
        _finishButton = [[UIButton alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.bounds) - kFinishButtonHeight, CGRectGetWidth(self.bounds), kFinishButtonHeight)];
        _finishButton.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
        [_finishButton setBackgroundColor:[UIColor blueColor]];
        [_finishButton setTitle:@"完 成" forState:UIControlStateNormal];
        [_finishButton addTarget:self action:@selector(finishButtonAction:) forControlEvents:UIControlEventTouchUpInside];
        
        [self addSubview:_finishButton];
    }
    
    #pragma mark - TableView Delegate
    
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
    {
        return kTableViewHeaderHeight;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return kTableViewCellHeight;
    }
    
    #pragma mark - TableView DataSource Delegate
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return _sections.count;
    }
    
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
    {
        return _sections[section];
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return [_options[section] count];
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSString *optionName = _options[indexPath.section][indexPath.row];
        
        if ([optionName isEqualToString:@"跟随模式"])
        {
            return [self tableViewCellForViewMode];
        }
        else if ([optionName isEqualToString:@"昼夜模式"])
        {
            return [self tableViewCellForNightType];
        }
        
        return nil;
    }
    
    #pragma mark - Custom TableView Cell
    
    - (UITableViewCell *)tableViewCellForViewMode
    {
        UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"ViewModeCellIdentifier"];
        
        _viewModeSeg = [[UISegmentedControl alloc] initWithItems:@[@"正北朝上" , @"车头朝上"]];
        [_viewModeSeg setFrame:CGRectMake(160, (kTableViewCellHeight - 30)/2.0, 150, 30)];
        _viewModeSeg.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
        [_viewModeSeg setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} forState:UIControlStateNormal];
        [_viewModeSeg addTarget:self action:@selector(viewModeSegmentedControlAction:) forControlEvents:UIControlEventValueChanged];
        
        UILabel *optionNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 120, kTableViewCellHeight)];
        optionNameLabel.textAlignment = NSTextAlignmentLeft;
        optionNameLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
        optionNameLabel.font = [UIFont systemFontOfSize:18];
        optionNameLabel.text = @"跟随模式:";
        
        if (self.trackingMode == AMapNaviViewTrackingModeMapNorth)
        {
            [_viewModeSeg setSelectedSegmentIndex:0];
        }
        else if (self.trackingMode == AMapNaviViewTrackingModeCarNorth)
        {
            [_viewModeSeg setSelectedSegmentIndex:1];
        }
        
        [cell.contentView addSubview:optionNameLabel];
        [cell.contentView addSubview:_viewModeSeg];
        
        return cell;
    }
    
    - (UITableViewCell *)tableViewCellForNightType
    {
        UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"ViewModeCellIdentifier"];
        
        UILabel *optionNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 120, kTableViewCellHeight)];
        optionNameLabel.textAlignment = NSTextAlignmentLeft;
        optionNameLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
        optionNameLabel.font = [UIFont systemFontOfSize:18];
        optionNameLabel.text = @"昼夜模式:";
        
        _nightTypeSeg = [[UISegmentedControl alloc] initWithItems:@[@"白天" , @"黑夜"]];
        _nightTypeSeg.frame = CGRectMake(160, (kTableViewCellHeight - 30)/2.0, 150, 30);
        _nightTypeSeg.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
        [_nightTypeSeg setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} forState:UIControlStateNormal];
        [_nightTypeSeg addTarget:self action:@selector(nightTypeSegmentedControlAction:) forControlEvents:UIControlEventValueChanged];
        
        [_nightTypeSeg setSelectedSegmentIndex:self.showNightType];
        
        [cell.contentView addSubview:optionNameLabel];
        [cell.contentView addSubview:_nightTypeSeg];
        
        return cell;
    }
    
    #pragma mark - UISegmentedControl Action
    
    - (void)viewModeSegmentedControlAction:(id)sender
    {
        NSInteger selectedIndex = [(UISegmentedControl *)sender selectedSegmentIndex];
        
        if (self.delegate && [self.delegate respondsToSelector:@selector(moreMenuViewTrackingModeChangeTo:)])
        {
            [self.delegate moreMenuViewTrackingModeChangeTo:(AMapNaviViewTrackingMode)selectedIndex];
        }
    }
    
    - (void)nightTypeSegmentedControlAction:(id)sender
    {
        NSInteger selectedIndex = [(UISegmentedControl *)sender selectedSegmentIndex];
        
        if (self.delegate && [self.delegate respondsToSelector:@selector(moreMenuViewNightTypeChangeTo:)])
        {
            [self.delegate moreMenuViewNightTypeChangeTo:selectedIndex];
        }
    }
    
    #pragma mark - Finish Button Action
    
    - (void)finishButtonAction:(id)sender
    {
        if (self.delegate && [self.delegate respondsToSelector:@selector(moreMenuViewFinishButtonClicked)])
        {
            [self.delegate moreMenuViewFinishButtonClicked];
        }
    }
    

    至此,导航功能已经完结,如果感觉有帮助请打赏,欢迎评论、点赞哦!!!☺☺

    相关文章

      网友评论

      • Fintecher:我的 [[AMapNaviDriveManager alloc] init];会crash, 楼主遇到过没?
        我用的是5.0.1b版本的导航
      • ea178e3dfb4b:有做添加途径点吗,求指教啊。
      • FongG:大兄弟,无名道路怎么解决啊啊啊啊啊啊啊!
      • 梁森的简书:代码太多,请原谅我没看完就提问。
        实时导航,只需要传递一个起始点和终点的坐标就可以了吗?
      • LauHao:可以贴一下源码吗
      • 简书不欢迎的程序员:楼主,,这个_currentUL 没有初始化,拿不用户当前位置啊
        attackGiant:@看山顶的那只蜗牛 这个好像是在上个页面传过来的,你可以自己获取一下
      • 4c8fd9ddcb74:楼主,这个导航车头方向咋一直不变的,能根据用户方向改变而改变吗,不变没办法有直观看到自己所处的方向
        梁森的简书:我这个尖头的方向也是没变,有人说是得在屋外,这个我还没试
        attackGiant:@4c8fd9ddcb74 导航的时候是实时获取的位置信息,怎么可能方向不变呢。
      • 花开成诗:讲解很详细,还贴心的贴上代码.留下来慢慢学习
      • LuckiestMan:刚好需要,感谢楼主无私分享!

      本文标题:【iOS】高德地图MAMapKit的使用:导航功能。

      本文链接:https://www.haomeiwen.com/subject/roongttx.html